Reputation: 188
I have a objectA list, each one contain an another objectB list. I'm trying to OrderBy each objectB list with an (int) Id :
var sorted = objectA.OrderBy(a => a.ObjectB.OrderBy(b => b.Id)).ToList();
Of course, this doesn't work. Someone have an advice ?
Upvotes: 2
Views: 7037
Reputation: 51204
If you want to sort each ObjectB
list in place (i.e. modify it), then simply use the List<T>.Sort
method. You will need to specify a custom Comparison<T>
delegate:
foreach (var a in objectA)
{
a.ObjectB.Sort((x, y) => x.Id - y.Id)
}
If objectA
is a List<ObjectA>
, then you can use the ForEach
method and pass a delegate:
objectA.ForEach(a => a.ObjectB.Sort((x, y) => x.Id - y.Id));
If you don't want to modify your original ObjectA
instances, then you will have to project each ObjectA
instance into a new instance (by cloning it) and then assign sorted ObjectB
lists. It would look something like (presuming that all properties have public setters):
var newList = objectA
.Select(x => new ObjectA()
{
Id = x.Id,
SomethingElse = x.SomethingElse,
ObjectB = x.ObjectB.OrderBy(b => b.Id).ToList()
})
.ToList();
Upvotes: 4
Reputation:
You can prepare extension method and use it at a generic way. For first, helpers for Expression
:
public static void SetProperty<T, B>(
this Expression<Func<T, B>> propertySelector,
T target,
B value)
{
SetObjectProperty(target, propertySelector, value);
}
public static void SetObjectProperty<T, B>(
T target,
Expression<Func<T, B>> propertySelector,
object value)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (propertySelector == null)
{
throw new ArgumentNullException("propertySelector");
}
var memberExpression = propertySelector.Body as MemberExpression;
if (memberExpression == null)
{
throw new NotSupportedException("Cannot recognize property.");
}
var propertyInfo = memberExpression.Member as PropertyInfo;
if (propertyInfo == null)
{
throw new NotSupportedException(
"You can select property only."
+ " Currently, selected member is: "
+ memberExpression.Member);
}
propertyInfo.SetValue(target, value);
}
Then write this extension:
public static IEnumerable<TSource> OrderInnerCollection<TSource, TInner, TKey>(
this IEnumerable<TSource> source,
Expression<Func<TSource, IEnumerable<TInner>>> innerSelector,
Func<TInner, TKey> keySelector)
{
var innerSelectorDelegate = innerSelector.Compile();
foreach (var item in source)
{
var collection = innerSelectorDelegate(item);
collection = collection.OrderBy(keySelector);
innerSelector.SetProperty(item, collection);
yield return item;
}
}
And usage:
var result = objectA.OrderInnerCollection(
aObj => aObj.ObjectB,
objB => objB.Id).ToList();
Upvotes: 0