2016-12-03 3 views
-1

私は以下のようなデータ構造を持っています。辞書のリストから単一の値を選択する方法は?

Dictionary<Blopp, List<double>> data = ...; 

これは実際には辞書のリストのようなものです。そして今、私はそれらのそれぞれに個別にアクセスする必要があります。だから私はこれのようなものを得るために探しています。

for(int i = 0; i < data.First().Value.Count; i++) 
{ 
    Dictionary<Blopp, double> partial = ...; 
    // do stuff to the partial number i 
} 

どうすればいいですか?

私はグーグルで語っていますが、私が探しているものをgoolenglishで説明するのはちょっと難しいです。 。:(どうやら

編集

、グーグルだけでなく、紛らわしい入手困難だったので、提案されているように、私は、データベースの例を提供しています

州の前に:

{A:{Q、E、W、R}、B:{、Sは、D、F}、C:{Z、X、C、V}}

状態は、第ITERATに要求外側ループのイオン。

{A:Q、B:、C:Z}外側ループの2回目の反復のために要求さ

状態。

{A:B、W:S、C:X}外側ループの第3の反復のために要求さ

状態。

{A:E、B:D、C:C}上記擬似例で

下部外装ながら、大文字はダブルスに対応するキーを表します。

+2

キーリストペアを含む辞書が1つあります。辞書リストはありません – user3185569

+0

@ user3185569はい、わかっています。しかし、**私は辞書のリストを持っているかのように見なすことができますが、お互いに課しています。 * Value *のリストの各要素は、他のKey-Valueペアの要素と、同じリスト内のバディの要素との関連性が高くなります。 –

+0

@ KonradViltersten:A:3 | B:4 | C:5とA:2 | B:9 | C:7の2つの辞書を考えてみましょう。もう1つはあなたが得られるでしょう:A:3,2 | B:4,9 | C:5,7 ...それはあなたが意味することですか? – digEmAll

答えて

1

あなたはこれを行うことができますLINQを使用して分離された辞書のリストに追加します。

List<Dictionary<Blopp,double>> listOfDict = 
Enumerable.Range(0,data.First().Value.Count) 
      .Select(i => data.ToDictionary(x => x.Key, x => x.Value[i])) 
      .ToList(); 

EDIT:

までのアプローチの両方が使い捨ての辞書の多くを作成します。もちろん、これらを変更する必要がなく、参照のみを実行する必要がある場合は、これは効率的で無駄です。免責事項

foreach (var partial in dict.AsSeparatedDictionaries()) 
{ 
    // use partial as a normal IDictionary<Blopp,double> 
    // if you need the current "i" use partial.Index 
} 


static class MultiDictionaryExtension 
{ 
    #region Extension 
    public static IEnumerable<IDictionary<TK, TV>> AsSeparatedDictionaries<TK, TV>(this IDictionary<TK, List<TV>> multiDict) 
    { 
     int numDictionaries = multiDict.First().Value.Count; 
     for (int i = 0; i < numDictionaries; i++) 
      yield return new SingleDictionaryWrap<TK, TV>(multiDict, i); 
    } 
    #endregion 

    #region Helper classes 
    public class SingleDictionaryWrap<TK, TV> : IDictionary<TK, TV> 
    { 
     private class ValueCollection : ICollection<TV> 
     { 
      private readonly SingleDictionaryWrap<TK, TV> dict; 
      public ValueCollection(SingleDictionaryWrap<TK, TV> dict) 
      { 
       this.dict = dict; 
      } 
      public int Count { get { return this.dict.Count; } } 
      public bool IsReadOnly { get { return false; } } 
      public void Add(TV item) { throw new NotSupportedException("This dictionary is readonly"); } 
      public void Clear() { throw new NotSupportedException("This dictionary is readonly"); } 
      public bool Contains(TV item) { return this.dict.Select(x => x.Value).Contains(item); } 
      public void CopyTo(TV[] array, int arrayIndex) { foreach (var item in this) array[arrayIndex++] = item; } 
      public IEnumerator<TV> GetEnumerator() { return this.dict.Select(x => x.Value).GetEnumerator(); } 
      public bool Remove(TV item) { throw new NotSupportedException("This dictionary is readonly"); } 
      IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } 
     } 

     private readonly IDictionary<TK, List<TV>> multiDict; 
     public int Index { get; private set; } 
     public SingleDictionaryWrap(IDictionary<TK, List<TV>> multiDict, int index) 
     { 
      this.Index = index; 
      this.multiDict = multiDict; 
     } 

     public ICollection<TK> Keys { get { return this.multiDict.Keys; } } 
     public ICollection<TV> Values { get { return new ValueCollection(this); } } 
     public int Count { get { return this.multiDict.Count; } } 
     public bool IsReadOnly { get { return true; } } 
     public TV this[TK key] 
     { 
      get { return this.multiDict[key][this.Index]; } 
      set { throw new NotSupportedException("This dictionary is readonly"); } 
     } 
     public bool ContainsKey(TK key) { return this.multiDict.ContainsKey(key); } 
     public void Add(TK key, TV value) { throw new NotSupportedException("This dictionary is readonly"); } 
     public bool Remove(TK key) { throw new NotSupportedException("This dictionary is readonly"); } 
     public bool TryGetValue(TK key, out TV value) 
     { 
      value = default(TV); 
      List<TV> values; 
      if (this.multiDict.TryGetValue(key, out values)) 
      { 
       value = values[this.Index]; 
       return true; 
      } 
      return false; 
     } 
     public void Add(KeyValuePair<TK, TV> item) { throw new NotSupportedException("This dictionary is readonly"); } 
     public void Clear() { throw new NotSupportedException("This dictionary is readonly"); } 
     public bool Contains(KeyValuePair<TK, TV> item) 
     { 
      TV value; 
      if (this.TryGetValue(item.Key, out value)) 
      { 
       return Object.Equals(value, item.Value); 
      } 
      return false; 
     } 
     public void CopyTo(KeyValuePair<TK, TV>[] array, int arrayIndex) { foreach (var kvp in this) array[arrayIndex++] = kvp; } 
     public bool Remove(KeyValuePair<TK, TV> item) { throw new NotSupportedException("This dictionary is readonly"); } 
     public IEnumerator<KeyValuePair<TK, TV>> GetEnumerator() { return this.multiDict.Select(kvp => new KeyValuePair<TK, TV>(kvp.Key, kvp.Value[this.Index])).GetEnumerator(); } 
     IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } 
    } 
    #endregion 
} 

かなり長い拡張クラスを、それはすべてが簡単になる方法を見て:だから、私はいくつかのラッパークラスを利用し、拡張メソッドのために行くだろうすべての前のコードは、すべての内部リストがまったく同じ長さであることを前提としています。

+0

あります。そんなに。それらは月なので、常に12です。 :) –

+0

OPはこれを別の返信で述べています:_ "明らかにするために、私は個々の要素にアクセスする方法を探しているわけではありませんが、私はLINQ変換を探して、結果は重複したキーを持たず、元のキーと同じキーのセットを持ちます。しかし、倍精度のリストの代わりに、単一の倍精度(位置iにあるもの)があります。 " - このコメントに基づいて、彼が後にしていることは、より多くの行にあると信じています:' data.ToDictionary(x => x .Key、y => y.Value [1]) ' - 同じ辞書ですが、1つのdoubleにフィルターされています –

+0

@MetroSmurfはい、OPはそれを示しています。 –

2

私はこれがあなたの意図したものだと思う:

for (int i = 0; i < data.First().Value.Count; i++) 
{ 
    var partial = data.ToDictionary(x => x.Key, x => x.Value.ElementAt(i)); 

    Console.WriteLine("i={0}", i); 
    foreach(var item in partial) 
    { 
     Console.WriteLine("Key={0} Value={1}",item.Key, item.Value); 
    } 
} 

出力:

var firstEntry = data.First(); 
for(int i = 0; i < firstEntry.Value.Count; i++) 
{ 
    Dictionary<Blopp, double> partial = data.ToDictionary(x => x.Key, x => x.Value[i]); 
    // do stuff to the partial number i 
} 

それとも、全体のデータになることができます:

i=0 
Key=A Value=q 
Key=B Value=a 
Key=C Value=z 
i=1 
Key=A Value=w 
Key=B Value=s 
Key=C Value=x 
i=2 
Key=A Value=e 
Key=B Value=d 
Key=C Value=c 
i=3 
Key=A Value=r 
Key=B Value=f 
Key=C Value=v 
+0

これは* Dictionary partial *型の構造体を選択しません。すべての要素を反復処理するだけです。私はLINQが1回のスワイプでこれを行うことを望んでいました。それらをすべてループして辞書を作成するのが最後の手段です。 –

+0

@KonradVilterstenそれを行うことができます。私はその答えを編集します。辞書は重複したキーを持つことができないので、辞書ではありません! – user3185569

+0

だから、明確にする。私は** ** ** ** ** **要素にアクセスする方法を探していません**。私は元のリストから**単一の**要素を含む**辞書**を得るためにLINQ変換を探しています。結果に重複キーはありません。元の鍵と同じセットの鍵を持ちます。しかし、ダブルスの代わりにシングルダブル(ポジション* i *にあるもの)があります。 –

0

私はこれがあなたの望むことを信じます。これを行う簡単な方法があるかもしれません。もし私がそれを考えたら、答えを更新します。内側のリストが同じ長さを持たない場合でもこのコードは機能します。

static void Main(string[] args) 
{ 
    Dictionary<Blopp, List<double>> data = CreateData(); 

    List<Dictionary<Blopp, double>> result = PiviotDictionary(data).ToList(); 
} 

private static IEnumerable<Dictionary<TKey, TValue>> GetSingleEntires<TKey,TValue>(Dictionary<TKey, List<TValue>> data) 
{ 
    bool foundValue = true; 
    for(int i = 0; foundValue == true; i++) 
    { 
     foundValue = false; 
     var result = new Dictionary<TKey, TValue>(); 
     foreach (var kvp in data) 
     { 
      if (kvp.Value.Count > i) 
      { 
       foundValue = true; 
       result.Add(kvp.Key, kvp.Value[i]); 
      } 
     } 

     if (foundValue) 
      yield return result; 

    } 
} 
関連する問題