2017-03-31 5 views
0

ボトムライン以下のコードと同じリストを返すlinq文が必要です。リストからのリストのフィルタリング

私はこれが可能なように感じています。私があきらめる前に、私は非常に近くにいるように感じて、より多くのコード行で欲しいものを綴っています。

私は未来のために達成しようとしていることを示すことができ、私が持っているものを置き換えることができる誰もが大変感謝しています。

public ObservableCollection<VarItem> IndexChannels 
{ 
    get 
    { 
     ObservableCollection<VarItem> filtered = new ObservableCollection<VarItem>(); 

     filtered.Add(indexChannels.First());//add Disabled no matter what 

     //add the cur channels selected index if it isn't already disabled 
     if (!filtered.Contains(indexChannels.FirstOrDefault(i => i == CurChannel.IndexChannel))) 
     { 
      filtered.Add(indexChannels.FirstOrDefault(i => i == CurChannel.IndexChannel)); 
     } 

     foreach (PdioChannelModel ch in channels) 
     { 
      //if the channels mode isn't q-decode or quad index add its Number as an index 
      if (ch.Mode.Value != "Q-Decode" && ch.Mode.Value != "Quad Index") 
      { 
       filtered.Add(indexChannels.FirstOrDefault(i => i.ID == ch.Number)); 
      } 
     } 
     return filtered; 
    } 
} 

VarItem

の基本的な構造

パブリッククラスVarItem { 公共int型のID {取得します。プライベートセット; } 公開ストリング値{get;プライベートセット; } public Dictionary MetaData {get;}プライベートセット; }

public VarItem(int id, string value) 
    { 
    this.ID = id; 
    this.Value = value; 
    MetaData = new Dictionary<string, string>(); 
    } 

例マスターリストVarItems含ま:

-1、

1 "無効"、 "チャンネル1"

2、 "チャンネル2"

3、 "チャネル3"

フィルタリストには常にVarItem(-1, Disabled)が含まれている必要があります。また、VarItemどこID試合CurChannel.IndexChannelが含まれている必要がありますし、最後にそれは私が私に知らせて必要なすべての詳細を逃した場合はIDがPdioChannelModel.Mode.Value != "Q-Decode" or "Quad Index"

任意のPdioChannelModel.Numberに一致するVarItem Sが含まれていsould。私があなたを混乱させ、多くの人に書いたり、明確化が必要な場合は、私にも知らせてください。

+0

あなたは、LINQの単一ビットをすべてそのコードを交換したり、foreachのビットをjsutしようとしています:ここで

は例のソリューションです3つの異なるもの(デフォルト、現在のもの、フィルタされたもの)はおそらく、それらのものを分離しておくことがより読みやすいことを意味します。 foreachはおそらくかなり簡単に 'filtered.AddRange'に変更することができ、Whereはあなたが望むものならSelectを続けますが、やはり"壊れていなければ修正しない "という傾向になります。もちろん、次回の学習の練習としても役立ちます... :) – Chris

+0

いくつかの質問があります。 「チャンネル」はどこから来たのですか? 'indexChannels'と同じ型ですか? 'IndexChannels'(大文字I)はtypoですか? 'indexChannels.First()'は常に "Disabled"の項目になっていますか?私はこれがフィルタリングとソートによって達成できると思います。 –

答えて

0

1つの方法は、追加するアイテムのリストを生成して、コンストラクタに渡すことです。

indexChannelsの最初のアイテムが必要で、現在のチャンネルが選択されている場合はそれが表示されていることがわかります。その部分はかなり簡単です。ちょうどnew List<VarItem>です。

次に、モードがQデコードまたはクワッドインデックスでないチャネルの番号と一致するIDを持つすべてのインデックスチャネルを追加します。だから、私はUnionを使ってこれを最初のリストと結合します。

そして最後に、FirstOrDefaultを返すデフォルト値についてdefault(VarItem)以来、私たちは最後にそれらを削除することができ、我々は我々が重複していないことを確実にするためにもそこにDistinctを投げることができます。

get 
{ 
    return new ObservableCollection<VarItem>((
     new List<VarItem> 
     { 
      indexChannels.First(), 
      indexChannels.FirstOrDefault(i => i == CurChannel.IndexChannel) 
     }) 
     .Union(channels 
      .Where(ch => ch.Mode.Value != "Q-Decode" && 
         ch.Mode.Value != "Quad Index") 
      .Select(ch => indexChannels.FirstOrDefault(i => i.ID == ch.Number))) 
     .Where(varItem => varItem != default(VarItem)) 
     .Distinct()); 
} 

ちょうど記録のために、私は生産コードでこれを行うことはありません。そのステートメントの失敗は、デバッグするのに非常に苦労します。一般に、1行につき1つの文を実行する方が、1行が失敗したときに他の人が読みやすく、デバッグしやすくなります。

0

nullの値をObservableCollectionに追加すると気になりますか? nullの値を除外する場合は、foreachの中でFirstOrDefaultが正しい方法ではありません。一方、すべてのチャネルNumberのプロパティがに少なくとも1回以上のに存在することがわかっている場合は、Firstを使用してください。あなたの前提が間違っている場合(NumberIDと一致しない場合)、Firstは例外をスローします。これは後でNullReferenceExceptionの代わりにデバッグするのが難しいでしょう。さらに、すべてのチャネルNumberindexChannelsに1回しか存在しないことがわかっている場合は、Singleを使用してください。したがって、この2番目の仮定に違反すると例外が発生します。これは、あとで予期しない動作よりも簡単にデバッグすることができます。あなたはおそらく書くことができながら、一つのコマンド事実として、それが効果的にやっているので

return new ObservableCollection<VarItem>(
    indexChannels 
    .Take(1) 
    .Union(indexChannels.Where(i => i == CurChannel.IndexChannel).Take(1)) 
    .Union(channels 
     .Where(c => c.Mode.Value != "Q-Decode" && 
        c.Mode.Value != "Quad Index") 
     // The following line could be turned into 
     // .Select(c => indexChannels.First(i => i.ID == c.Number)) 
     // OR 
     // .Select(c => indexChannels.Single(i => i.ID == c.Number)) 
     // OR 
     // .SelectMany(c => indexChannels.Where(i => i.ID == c.Number)) 
     // depending on how many channels in indexChannels 
     // are expected to match each Number property. 
     .Select(c => indexChannels.FirstOrDefault(i => i.ID == c.Number)) 
); 
関連する問題