Мой 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 - Производитель (... снизил список...),
Я думаю, что Брайан довольно хорошо инкапсулировал логику сортировки, и я не думал об этом. В любом случае я хотел бы представить свой взгляд на это на примере 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, перемещенные наверх, а затем оставшиеся в исходном порядке.
Правка оказывается Distinct ()
не требуется, исправленный код:
Это то, что вы хотите?
var result =
products
.GroupBy(x => x.Id)
.Take(numberOfFeatures)
.Select(x => x.First())
.Union(products);
return result.ToList();
Обратите внимание, что GroupBy будет иметь правильную последовательность , а Union также
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;
}
}
}
Если я правильно вас понимаю, думаю, это сработает для вас.
Вы спрашиваете, какие первые «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());
}