这可以按如下方式完成。首先,为您的订单引入一个数据模型,如下所示:
public class Order
{
public string[] order { get; set; }
}
接下来,为枚举定义以下相等比较器:
public class IEnumerableComparer<TEnumerable, TElement> : IEqualityComparer<TEnumerable> where TEnumerable : IEnumerable<TElement>
{
//Adapted from IEqualityComparer for SequenceEqual
//https://stackoverflow.com/questions/14675720/iequalitycomparer-for-sequenceequal
//Answer https://stackoverflow.com/a/14675741 By Cédric Bignon https://stackoverflow.com/users/1284526/c%C3%A9dric-bignon
public bool Equals(TEnumerable x, TEnumerable y)
{
return Object.ReferenceEquals(x, y) || (x != null && y != null && x.SequenceEqual(y));
}
public int GetHashCode(TEnumerable obj)
{
// Will not throw an OverflowException
unchecked
{
return obj.Where(e => e != null).Select(e => e.GetHashCode()).Aggregate(17, (a, b) => 23 * a + b);
}
}
}
现在您可以反序列化包含上面列出的订单的 JSON,并按如下所示的频率降序对唯一订单进行排序:
var items = JsonConvert.DeserializeObject<List<Order>>(jsonString);
//Adapted from LINQ: Order By Count of most common value
//https://stackoverflow.com/questions/20046563/linq-order-by-count-of-most-common-value
//Answer https://stackoverflow.com/a/20046812 by King King https://stackoverflow.com/users/1679602/king-king
var query = items
//If order items aren't already sorted, you need to do so first.
//use StringComparer.OrdinalIgnoreCase or StringComparer.Ordinal or StringComparer.CurrentCulture as required.
.Select(i => i.order.OrderBy(s => s, StringComparer.Ordinal).ToArray())
//Adapted from writing a custom comparer for linq groupby
//https://stackoverflow.com/questions/37733773/writing-a-custom-comparer-for-linq-groupby
//Answer https://stackoverflow.com/a/37734601 by Gert Arnold https://stackoverflow.com/users/861716/gert-arnold
.GroupBy(s => s, new IEnumerableComparer<string [], string>())
.OrderByDescending(g => g.Count())
.Select(g => new Order { order = g.Key } );
var sortedItems = query.ToList();
演示小提琴here.
或者,如果你想保留重复而不是合并它们,你可以这样做:
var query = items
//If order items aren't already sorted, you may need to do so first.
//use StringComparer.OrdinalIgnoreCase or StringComparer.Ordinal or StringComparer.CurrentCulture as required.
.Select(i => i.order.OrderBy(s => s, StringComparer.Ordinal).ToArray())
//Adapted from writing a custom comparer for linq groupby
//https://stackoverflow.com/questions/37733773/writing-a-custom-comparer-for-linq-groupby
//Answer https://stackoverflow.com/a/37734601 by Gert Arnold https://stackoverflow.com/users/861716/gert-arnold
.GroupBy(s => s, new IEnumerableComparer<string [], string>())
.OrderByDescending(g => g.Count())
.SelectMany(g => g)
.Select(a => new Order { order = a });
演示小提琴#2 here.
注意事项:
我使用两个泛型类型IEnumerableComparer<TEnumerable, TElement> : IEqualityComparer<TEnumerable> where TEnumerable : IEnumerable<TElement> 定义相等比较器,而不仅仅是IEnumerableComparer<string>,如Cédric Bignon 的this answer 到IEqualityComparer for SequenceEqual 所示,以防止string [] 通过.GroupBy(s => s, new IEnumerableComparer<string>()) lambda 表达式中的类型推断,将键从向上转换为IEnumerable<string>。
如果您确定订单已经排序,或者["Order3", "Order1"] 与["Order1", "Order3"] 不同,则将i.order.OrderBy(s => s, StringComparer.Ordinal).ToArray() 替换为i.order。