按ID列表排列对象列表

时间:2017-12-15 11:50:23

标签: c# linq

所以,我有一个对象列表(让我们说有20个)并且他们有一个id。然后我有另一个列表(正确排序)。 我有这个linq通过id列表对对象列表进行排序:

var outcomeIds = outcomeRequestModels
  .OrderByDescending(m => m.Score)
  .Select(m => m.Id)
  .ToList();

groupResponseModel.Outcomes = groupOutcomes
  .OrderBy(m => outcomeIds.IndexOf(m.Id))
  .ToList();

现在,这个"会"工作,但问题是 outcomeIds 只有一个选择的ID。我原以为indexOf会为任何未找到的ID返回-1,并将其放在匹配的ID下。相反,它们首先出现在列表中。 如何修改我的代码以使匹配的ID位于顶部,其余位于底部。我不能做反向,因为这意味着匹配ID的顺序也会相反。

4 个答案:

答案 0 :(得分:2)

听起来你想要按IndexOf的结果排序,但让-1值到达结尾而不是开始。在这种情况下,您可以只将IndexOf的值处理为int.MaxValue,以便最终结束。

我已经整理了您的代码以使其更具可读性 - 只有OrderBy与原始代码不同。

var outcomeIds = outcomeRequestModels
    .OrderByDescending(m => m.Score)
    .Select(m => m.Id)
    .ToList();

groupResponseModel.Outcomes = groupOutcomes
    .Select(m => Tuple.Create(m, outcomeIds.IndexOf(m.Id))
    .OrderBy(m => outcomeIds.IndexOf(m.Id) == -1 ? int.MaxValue : outcomeIds.IndexOf(m.Id))
    .ToList();

或者,如果您不想多次调用IndexOf,可以将条件语句提取到方法中:

var outcomeIds = outcomeRequestModels
    .OrderByDescending(m => m.Score)
    .Select(m => m.Id)
    .ToList();

groupResponseModel.Outcomes = groupOutcomes
    .Select(m => Tuple.Create(m, outcomeIds.IndexOf(m.Id))
    .OrderBy(m => orderByKeySelector(outcomeIds(m.Id)))
    .ToList();

其中orderByKeySelector

private static int orderByKeySelector<T>(List<T> source, T value)
{
    var indexOfValue = source.IndexOf(value);
    return indexOfValue == -1 ? int.MaxValue : indexOfValue;
}

答案 1 :(得分:1)

var outcomeIds = outcomeRequestModels
  .OrderByDescending(m => m.Score)
  .Select(m => m.Id)
  .ToList();

groupResponseModel.Outcomes = groupOutcomes
  .OrderBy(m => outcomeIds.IndexOf(m.Id) != -1
     ? outcomeIds.IndexOf(m.Id) 
     : outcomeIds.Max())
  .ToList();

答案 2 :(得分:0)

我更喜欢保持简单:

var outcomeList;
var unorderedList;

//check all elements of the ordered list in order
foreach(var item in orderedList) 
{
    //if your unordered list has this item
    if(unorderedList.Any(item))
    {
        //add this item to the final list
        outcomeList.Add(item);
        //and remove it from unordered
        unorderedList.Remove(item);
    }
}

//at this point, you added all your matching entities in order, the rest is the remainder:

outcomeList.AddRange(unorderedList);

您甚至可以将其转换为可重用性的扩展方法。

答案 3 :(得分:0)

为什么不在字典的帮助下使用映射(例如,id == 5对应0id = 1231等)?在长列表的情况下它会很有效:

var order = outcomeRequestModels
  .OrderByDescending(m => m.Score)
  .Select((m, index) => new {
     id = m.id,
     index = index }) 
  .ToDictionary(item => item.id,      // id
                item => item.index);  // corresponding index

现在让我们排序第二个列表:

groupResponseModel.Outcomes = groupOutcomes
  .OrderBy(m => order.TryGetValue(m.Id, out var order) 
     ? order          // if we have corresponding index, use it   
     : int.MaxValue)  // otherwise, put the item at the bottom
  .ToList();