2017-12-15 3 views
1

したがって、私はオブジェクトのリストを持っています(20個あるとしましょう)。次に私は別のリスト(正しく注文されている)を持っています。 私はIDリストでオブジェクトのリストをソートするために、このLINQを持っていた:今idsのリストによるオブジェクトのリストの整列

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

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

、これは作品「希望」が、問題がはそれだけではIDの選択をしていoutcomeIdsです。私は、indexOfが見つかりませんでしたidのために-1を返すだろうと思っていただろうと、それは一致IDの下に置かれます。代わりに、リストの最初に表示されます。 どのようにコードを修正して、一致するIDを上部と下部の両方に取得することができますか?逆のことはできません。これは、一致するIDの順序が逆になることを意味するためです。

+2

あなたは、例えば入力のリスト、および予想される出力を与えることができますか?あなたのケースをはっきりとIMHOにするでしょう。 – Pac0

+3

[mcve](@ Pac0の提案を含む)はすばらしいでしょう。 – mjwills

+1

m =>(uint)outcomeIds.IndexOf(m.Id)はおそらく問題を解決します。しかし、実際には2回のマテリアライゼーションを使用するLINQは実際には20個のオブジェクトがある場合にのみあまり良くありません – vitalygolub

答えて

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
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(); 
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); 

これを拡張メソッドに変えて再利用することもできます。

0

なぜ辞書の助けを借りて(たとえば、id == 5id = 1231になど、0に相当)マッピングを使用していませんか?それは長いリストの場合に効率的になります。

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();  
関連する問題