Reputation: 10105
Looking for a built-in way (preferable one-liner) to reproduce this Python line in C#.
sorted_weights = sorted(weights, key=lambda weight: (weight[1], weight[0]))
It sorts the map/dictionary using first the value and if there are duplicated values, it should sort using keys. (please note: both, keys and values, are integers)
I'd like to avoid writing an own function/loop (which I am capable of ;)) to achieve sorting if not needed. I'm pretty sure there is a functional programming approach in C# for this as well, isn't there?
Upvotes: 0
Views: 1273
Reputation: 30474
A one-liner:
Assuming your Weights have properties Value and Key:
var sortedWeights = weights.SortedBy(weight => weight.Value).ThenBy(weight => weight.Key);
Apparently your input is a sequence of similar items, and you want to sort first by one property, followed by a sort in another property.
My advice would be to create an extension method. After that you can use it as a one-liner LINQ like method. See extension methods demystified
To make it reusable, your <int, int>
version calls a generic method:
public static IEnumerable<TSource> OrderBy<TSource, TSort1, TSort2>(
this IEnumerable<TSource> source,
Func<TSource, TSort1> sortProperty1,
Func<TSource, TSort2> sortProperty2)
{
return source.OrderBy(item => sortProperty1(item)
.ThenBy(item => sortProperty2(item);
}
Usage:
IEnumerable<Weight> weights = ...
// sort by Weight.Value then by Id:
var result = weights.OrderBy(weight => weight.Value, weight => weight.Id);
Or A dictionary, order by Weight.X then by dictionary key:
Dictionary<int, Weights> dict = ...
var result = dict.OrderBy(dictItem => dictItem.Value.X,
dictItem => dictItem.Key);
If you don't want to mention the second sort property, consider adding an extra extension method:
public static IEnumerable<KeyValuePair<TKey, TValue>> OrderByThenByKey<TKey, TValue, TProperty>(
// TODO: invent a proper method name
this IEnumerable<KeyValuePair<TKey, TValue>> source,
Func<TValue, TProperty> propertySelector)
{
// call the other OrderBy
return source.OrderBy(propertySelector, keyValuePair => keyValuePair.Key);
}
Usage:
Dictionary<int, Weight> dict = ...
var result = dict.OrderByThenByKey(weight => weight.X);
Upvotes: 2
Reputation: 930
Assuming weights
is a dictionary, you can try:
//using System.Linq;
var sortedWeights = weights.OrderBy(weight => weight.Value).ThenBy(weight => weight.Key);
Upvotes: 2
Reputation: 1852
I'm not 100% clear on what that Python code produces, but if it's a flat list of weight objects then this C# line does the same thing:
using System.Linq;
var sorted_weights = weights.OrderBy(weight => (weight[1], weight[0]));
Just be aware that output object is the equivalent of a Python generator. It will only be evaluated when you enumerate over it.
Upvotes: 1