LINQ排序 - 前三个需要是不同的制造商

时间:2010-03-19 04:43:33

标签: c# linq sorting

我的OM有一个“产品”对象 每个产品都有一个'制造商ID'(属性,整数) 当我有一个要显示的产品列表时,前三个显示为“特色产品” 该列表已按特定排序顺序排序,将“特色”产品放在列表中的第一位。

但是,我现在需要确保列表中的特色产品来自不同的制造商。我想有一个方法来调用这个重新排序。试图利用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 - 制造商A(第1特征)
产品2 - 制造商B(第二特征)
产品3 - 制造商C(第3特征)
产品4 - 制造商A(......未经检查......)
产品5 - 制造商A(......未经检查......)

e.g。调整案例......例如...... 输入列表
产品1 - 制造商A
产品2 - 制造商A
产品3 - 制造商B
产品4 - 制造商A
产品5 - 制造商F
(...我们希望...)
产品1 - 制造商A(第1特征)
产品3 - 制造商B(第二个特征......向上移动)
产品5 - 制造商F(第3个特征......向上移动)
产品2 - 制造商A(...推下列表......)
产品4 - 制造商A(......按下列表......)

4 个答案:

答案 0 :(得分:3)

我认为Bryan很好地封装了排序逻辑,这不是我想做的事情。无论如何,我想用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转移到顶部,其余的按照原来的顺序。

答案 1 :(得分:2)

<击>

<击>
    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();
    }

<击>

编辑:问题实际上是关于列表的自定义排序。我选择描述比较本身,并使用它来排序:

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

这是通过实施IComparer<Product>并跟踪遇到的制造商来完成的。如果少于3个,我们找到一个新产品,我们赞成该产品:

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 :(得分:1)

编辑结果不需要Distinct(),修改后的代码:

这是你想要的吗?

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

请注意,GroupBy将具有正确的sequence和Union将also

答案 3 :(得分:0)

如果我理解正确,我认为这对你有用。

您是否正在使用订购列表“产品”询问具有不同“ManufacturerId”的“Product”的第一个“numberOfFeatures”是什么?

public List<Product> SetFeatures(List<Product> products, int numberOfFeatures)
{
    return products
        .GroupBy(p => p.ManufacturerId)
        .Take(numberOfFeatures)
        .Select(g => g.First());
}