c#使用多个条件进行排序

时间:2017-06-02 13:03:16

标签: c# sorting

忍受我,我会尽量不要让这太复杂。我有一个产品清单。产品看起来像这样:

{
    "id": 3797,
    "title": "Canon EOS 100D Digital SLR Camera with 18-55 IS STM Lens, HD 1080p, 18MP, 3\" LCD Touch Screen",
    "shortTitle": "Canon EOS 100D Black",
    "brand": "Canon",
    "model": "EOS 100D",
    "colour": "Black",
    "gtin": "8714574602721",
    "image": "http://piiick.blob.core.windows.net/images/Canon-EOS-100D-18-55-Black-8714574602721.png",
    "type": "Digital SLR",
    "lensFocalLength": "18-55",
    "lensType": "IS STM",
    "lensMount": "EF/EF-S",
    "maxAperture": "999",
    "connectivity": "",
    "shootingModes": "Scene Intelligent Auto (Stills and Movie), No Flash, Creative Auto, Portrait, Landscape, Close-up, Sports, SCN(Kids, Food, Candlelight, Night Portrait, Handheld Night Scene, HDR Backlight Control), Program AE , Shutter priority AE, Aperture priority AE, Manual (Stills and Movie)",
    "weight": 410.0,
    "width": 116.8,
    "height": 90.7,
    "depth": 69.4,
    "digitalZoom": "N/A",
    "opticalZoom": "N/A",
    "waterproof": false,
    "maxVideoResolution": "1920 x 1080",
    "sensorType": "CMOS",
    "sensorSize": "22.3 x 14.9 mm",
    "continuousShootingSpeed": "4",
    "iso": "1600",
    "style": "traditional",
    "designer": "",
    "dateAnnounced": "10/06/2008",
    "focusPoints": 7
}

但为了帮助解释这一点,我将简化它。 我正在尝试创建一个允许对多列进行排序的排序方法。 例如,我有这个方法:

/// <summary>
/// Performs an advanced sort on products using sortations
/// </summary>
/// <param name="products">The products to sort</param>
/// <param name="sortations">The sortation list</param>
public void AdvancedSort(List<JObject> products, List<Sortation> sortations)
{

    // Get our value types
    GetTypesFromOperator(sortations);

    // Sort our products by the sortations
    products.Sort((a, b) =>
    {
        foreach (var sortation in sortations)
        {

            // Get our values
            var fieldName = sortation.Field;
            var x = a.SelectToken(fieldName).ToString();
            var y = b.SelectToken(fieldName).ToString();
            var type = sortation.Type;

            // If both values are the same, skip the rest of this iteration
            if (x.Equals(y)) return 0;

            // If we have an expression
            if (!string.IsNullOrEmpty(sortation.Expression))
            {

                // If we are checking for between
                if (sortation.Operator == "><")
                {

                    // Get our values
                    var values = sortation.Expression.Split(',');

                    // If we have 2 values
                    if (values.Length == 2)
                        return CompareBetween(values, x, y);
                }

                // If we are checking booleans
                if (sortation.Operator == "===")
                    return CompareBoolean(sortation.Expression);

                // If we are checking equals
                if (sortation.Operator == "=")
                    return y.Equals(sortation.Expression) ? 1 : -1;

                // If we are checking like
                if (sortation.Operator == "%")
                    return y.Equals(sortation.Expression, StringComparison.OrdinalIgnoreCase) ? 1 : -1;
            }

            // If we get this far, do a switch on sortation types
            switch (sortation.Type)
            {
                case SortationValueType.Boolean:
                    return Boolean.Parse(x) ? -1 : 1;
                case SortationValueType.Number:
                    return CompareNumeric(x, y, sortation.Direction);
                default:
                    return string.CompareOrdinal(x, y);
            }
        }

        // If nothing matches, return 0
        return 0;
    });
}

它正在尝试根据属性值类型和我称之为分类的内容进行排序。 分类只是一个规定要查询的运算符,表达式和字段的类。 这是分拣

的示例
// Add importance, expert and sponsored
sortations.Add(new Sortation
{
    Field = "importance",
    Operator = "<"
});

现在,我们可以动态添加许多不同的分类。我需要能够通过这些分类对产品进行排序。 我创建了一个简单的测试:

[Test]
public void SortBySilverColourSilverShouldBeTop()
{

    // Assemble
    var json = "[{ colour: 'Black', importance: '150' }, { colour: 'Black', importance: '150' }, { colour: 'Black', importance: '150' }, { colour: 'Silver', importance: '150' }, { colour: 'Black', importance: '149' }, { colour: 'Black', importance: '149' }, { colour: 'Black', importance: '149' }, { colour: 'Silver', importance: '149' }]";
    var products = JsonConvert.DeserializeObject<List<JObject>>(json);
    var sortations = new List<Sortation>() { new Sortation() { Field = "colour", Operator = "=", Expression = "Silver" }, new Sortation() { Field = "importance", Operator = "<" } };

    // Act
    _sortProvider.AdvancedSort(products, sortations);
    var result = products[0].SelectToken("colour").ToString();

    // Assert
    Assert.That(result, Is.EqualTo("Silver"));
}   

我希望这样,我会得到这个输出:

[  
   { colour:'Silver', Importance:'150'},
   { colour:'Black', Importance:'150' },
   { colour:'Black', Importance:'150' },
   { colour:'Black', Importance:'150' },
   { colour:'Silver', Importance:'149' },
   { colour:'Black', Importance:'149' },
   { colour:'Black', Importance:'149' },
   { colour:'Black', Importance:'149' }
]

但我得到了这个输出:

[  
   { colour:'Silver', Importance:'150' },
   { colour:'Silver', Importance:'149' },
   { colour:'Black', Importance:'150' },
   { colour:'Black', Importance:'150' },
   { colour:'Black', Importance:'150' },
   { colour:'Black', Importance:'149' },
   { colour:'Black', Importance:'149' },
   { colour:'Black', Importance:'149' }
]

有人可以帮我修复排序方法吗?

2 个答案:

答案 0 :(得分:2)

在我看来,你的基本问题是,只要第一次分拣遇到匹配,它就会将排序顺序值返回到排序功能,其余的排序根本不重要。我相信你需要做的是交换foreach和products.sort调用,如下所示:

// Get our value types
GetTypesFromOperator(sortations);

foreach (var sortation in sortations)
{
    // Sort our products by the sortations
    products.Sort((a, b) =>
    {
        // Get our values
        var fieldName = sortation.Field;
        var x = a.SelectToken(fieldName).ToString();
        var y = b.SelectToken(fieldName).ToString();
        var type = sortation.Type;
        ....
        ....
    }
}

这将花费更长时间,但会考虑每次分拣。请记住,列表中的最后一个分类将是最重要的。

答案 1 :(得分:1)

看起来你已经让他们倒退了 - 它把所有的“银牌”放在第一位,然后按重要性排序第二位。

尝试更换分拣顺序:

var sortations = new List<Sortation>() {
    new Sortation() { Field = "importance", Operator = "<" },
    new Sortation() { Field = "colour", Operator = "=", Expression = "Silver" }
};