LINQ, Сортирующий - Сначала три, должен быть различными производителями

Мой OM имеет объект 'продукта'.
Каждый продукт имеет 'идентификатор производителя' (свойство, целое число).
Когда у меня есть список продуктов для отображения, первые три отображены как 'представляемые продукты'.
Список уже отсортирован в определенном порядке сортировки, поместив 'известные' продукты сначала в списке.

Однако я теперь должен удостовериться, что представляемые продукты в списке от различных Производителей. Я хочу иметь метод для вызова, чтобы сделать это обращение. Попытка использовать LINQ к к запросам входа 'продукты' и 'результаты'

public List<Product> SetFeatures(List<Product> products, int numberOfFeatures)
{
    List<Product> result;

    // ensure the 2nd product is different manufacturer than the first ....

    // ensure the 3rd product is a different manufacturer than the first two... 

    // ... etc ... for the numberOfFeatures

    return result;

}

Заранее спасибо.

Разъяснение:
Исходный список находится в определенном порядке: 'наиболее продаваемое', самое высокое, первое (порядок по убыванию). Получающийся список должен остаться в этом порядке за исключением корректировки или продвижения объектов так, чтобы отличающиеся производители были замечены вершина n функции.

Если первый n (numberOfFeatures) объектов, у всех есть различные производители, то список не должен быть изменен вообще.
например, Если numberOfFeatures = 3
Продукт 1 - Производитель (1-я функция)
Продукт 2 - Производитель B (2-я функция)
Продукт 3 - Производитель C (3-я функция)
Продукт 4 - Производитель (... не проверенный...)
Продукт 5 - Производитель (... не проверенный...)

например, Случай для корректировки..., например... ВХОДНОЙ Список
Продукт 1 - производитель A
Продукт 2 - производитель A
Продукт 3 - производитель B
Продукт 4 - производитель A
Продукт 5 - производитель F
(... мы хотели бы...),
Продукт 1 - Производитель (1-я функция)
Продукт 3 - Производитель B (2-я функция... перемещенная вверх)
Продукт 5 - Производитель F (3-я функция... перемещенная вверх)
Продукт 2 - Производитель (... снизил список...),
Продукт 4 - Производитель (... снизил список...),

5
задан Rob 19 March 2010 в 13:31
поделиться

4 ответа

Я думаю, что Брайан довольно хорошо инкапсулировал логику сортировки, и я не думал об этом. В любом случае я хотел бы представить свой взгляд на это на примере Foo.

        List<Foo> foos = new List<Foo>()
    {
        new Foo() { Baz = 1, Blah = "A"},
        new Foo() { Baz = 2, Blah = "A"},
        new Foo() { Baz = 3, Blah = "B"},
        new Foo() { Baz = 4, Blah = "B"},
        new Foo() { Baz = 5, Blah = "B"},
        new Foo() { Baz = 6, Blah = "C"},
        new Foo() { Baz = 7, Blah = "C"},
        new Foo() { Baz = 8, Blah = "D"},
        new Foo() { Baz = 9, Blah = "A"},
        new Foo() { Baz = 10, Blah = "B"},
    };

    var query = foos.Distinct(new FooComparer()).Take(3).ToList();
    var theRest = foos.Except(query);

    query.AddRange(theRest);

FooComparer является

    public class FooComparer : IEqualityComparer<Foo>
{
    public bool Equals(Foo x, Foo y)
    {
        return x.Blah == y.Blah;
    }

    public int GetHashCode(Foo obj)
    {
        return obj.Blah.GetHashCode();
    }
}

Вы получаете (Baz) 1, 3 и 6, перемещенные наверх, а затем оставшиеся в исходном порядке.

3
ответ дан 14 December 2019 в 13:32
поделиться

Правка оказывается Distinct () не требуется, исправленный код:

Это то, что вы хотите?

var result = 
        products
            .GroupBy(x => x.Id)
            .Take(numberOfFeatures)
            .Select(x => x.First())
            .Union(products);
return result.ToList();

Обратите внимание, что GroupBy будет иметь правильную последовательность , а Union также

1
ответ дан 14 December 2019 в 13:32
поделиться

    public List SetFeatures(List products, int numberOfFeatures)
    {
        var manufacturerProducts =
            from product in products
            group product by product.ManufacturerId into productGroup
            select productGroup.First();

        return manufacturerProducts.Take(numberOfFeatures).ToList();
    }

Edit: Вопрос действительно касается пользовательского упорядочивания списка. Я решил описать само сравнение и использовать его для сортировки:

return products
    .OrderBy(product => product, new FeaturedProductComparer(numberOfFeatures))
    .ToList();

Это делается путем реализации IComparer и отслеживания производителей, которые встречались. Когда их становится меньше трех и мы находим новый, мы отдаем предпочтение этому продукту:

private class FeaturedProductComparer : IComparer<Product>
{
    // OrderBy preserves the order of equal elements
    private const int _originalOrder = 0;
    private const int _xFirst = -1;
    private const int _yFirst = 1;

    private readonly HashSet<int> _manufacturerIds = new HashSet<int>();
    private readonly int _numberOfFeatures;

    internal FeaturedProductComparer(int numberOfFeatures)
    {
        _numberOfFeatures = numberOfFeatures;
    }

    public int Compare(Product x, Product y)
    {
        return _manufacturerIds.Count == _numberOfFeatures
            ? _originalOrder
            : CompareManufacturer(x, y);
    }

    private int CompareManufacturer(Product x, Product y)
    {
        if(!_manufacturerIds.Contains(x.ManufacturerId))
        {
            _manufacturerIds.Add(x.ManufacturerId);

            // Sort existing featured products ahead of new ones
            return _manufacturerIds.Contains(y.ManufacturerId) ? _yFirst : _xFirst;
        }
        else if(!_manufacturerIds.Contains(y.ManufacturerId))
        {
            _manufacturerIds.Add(y.ManufacturerId);

            // Sort existing featured products ahead of new ones
            return _manufacturerIds.Contains(x.ManufacturerId) ? _xFirst : _yFirst;
        }
        else
        {
            return _originalOrder;
        }
    }
}
2
ответ дан 14 December 2019 в 13:32
поделиться

Если я правильно вас понимаю, думаю, это сработает для вас.

Вы спрашиваете, какие первые «numberOfFeatures» из «Product» имеют разные «ManufacturerId» с использованием упорядоченного списка «products»?

public List<Product> SetFeatures(List<Product> products, int numberOfFeatures)
{
    return products
        .GroupBy(p => p.ManufacturerId)
        .Take(numberOfFeatures)
        .Select(g => g.First());
}
0
ответ дан 14 December 2019 в 13:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: