2011-09-13 40 views
1

我有2 dictionnary與similaire strutureC# - 比較兩個詞典知道每個 「添加」 操作,每個 「刪除」 操作

Dictionary<string, List<int>> Origins 

Dictionary<string, List<int>> Changes 

我已創建之初起源。它是開始狀態的副本。 例子:

Origins["toto"] = new List<int>(){1,2,3}; 
Origins["tata"] = new List<int>(); 
Origins["titi"] = new List<int>(){1,2}; 

的用戶動作後,我守在變化dictionnary的變化。 基本上,用戶可以添加或刪除鏈接到字符串的一些數字。所以我一直是這樣的任何變化的所有痕跡:

例如:如果用戶在「塔塔」 在字典中添加1改變一個有 「塔塔」有1

如果用戶添加4在字典中的「TOTO」 更改一個具有 「TOTO」具有1,2,3,4

如果用戶在詞典中刪除1「蒂蒂」 更改一個具有 「蒂蒂」有2個

我需要更改dicti通過簡單的比較可以知道用戶何時回到原始狀態。

如果沒有對字符串進行更改,則更改字典中沒有此字符串的任何條目。

經過許多更改後,用戶可以保存更改。 所以現在我需要找到所有的添加和刪除操作。

我的第一個想法是比較兩個字典,看操作添加和操作刪除。但是如何? 如果我比較同一個字符串的列表,我可能會知道其中的差異,但我在這裏卡住了。 也許有更好的方法來做到這一點?任何建議?

回答

2

您有以下情況:

  1. 的新字符串鍵添加到Changes,與一些相關的值一起。
  2. 現有字符串鍵值已更改(添加或刪除值)。

如果是(1),您將在Changes中輸入一個不存在於Origins中的條目。在(2)的情況下,您將在兩個條目中都有一個條目,但具有不同的值列表。我想要假設的數值是一個數學集,即一個特定的值只能出現在那裏,而且這個排序並不重要,如果不是這種情況,那麼你將不得不稍微修改這個方法。 )

爲了檢測情況(1),你可以發現,是唯一的按鍵:

IEnumerable<string> newKeys = Changes.Keys.Except(Origins.Keys); 

顯然,對於一個新的密鑰在Changes每個值將需要「添加」。你可以簡單地迭代newKeys枚舉和Changes檢索值:

foreach (string key in newKeys) 
{ 
    IEnumerable<int> addedValues = Changes[key]; 
    // your processing here 
} 

要檢測的情況下(2),你將需要遍歷字典,並與起源比較設定值的變化的影響。爲此,我們將迭代Origins以獲取密鑰和原始值,然後使用Changes中的密鑰檢索項目。 (我們將圍繞做這種方式,如果我們迭代Changes相反,我們將可能與新結束,還說不Origins存在,這是我們不得不面對另一種情況鍵。)

foreach (KeyValuePair<string, List<int>> entry in Origins) 
{ 
    List<int> originsValues = entry.Value; 
    List<int> changesValues; 

    // handle no key in Changes (as pointed out by Guillaume V). 
    if (!Changes.TryGet(entry.Key, out changesValues)) changesValues = originsValues; 

    IEnumerable<int> removedValues = originsValues.Except(changesValues); 
    IEnumerable<int> addedValues = changesValues.Except(originsValues); 

    // your processing here 
} 
+0

List changesValues = Changes [entry.Key] .Value; 這可能會崩潰,因爲更改可能沒有鍵「entry.key」 –

+0

@Guillaume V:謝謝,我已經添加了處理這種情況。 –

1

你可以試試這個:

 Dictionary<string, List<int>> Origin = new Dictionary<string, List<int>>(); 

     Origin["toto"] = new List<int>(){1,2,3}; 
     Origin["tata"] = new List<int>(); 
     Origin["titi"] = new List<int>(){1,2}; 


     Dictionary<string, List<int>> Changes = new Dictionary<string,List<int>>(); 

     Changes["toto"] = new List<int>() { 1, 2, 3, 4 }; 
     Changes["tata"] = new List<int>(){1}; 
     Changes["titi"] = new List<int>() { 2 }; 

     Dictionary<string, List<int>> ToRemove = new Dictionary<string, List<int>>(); 
     Dictionary<string, List<int>> ToAdd = new Dictionary<string, List<int>>(); 

     foreach (string key in Origin.Keys) 
     { 
      ToRemove[key] = Origin[key]; 
      ToAdd[key] = Changes[key]; 


      foreach (int i in ToRemove[key]) 
      { 

       if (ToAdd[key].Contains(i)) //There is no change 
       { 
        ToAdd[key].Remove(i); 
        ToRemove[key].Remove(i); 
       } 
      } 
     } 
+0

添加[key] =更改[key];這可能會導致崩潰,因爲更改可能沒有密鑰「密鑰」 –

0

如果你需要做的就是確定兩個對象是相等的,我建議你創建自己的類,和壓倒一切的Equals()GetHashInfo()

public class ComparableDictionary : Dictionary<string, List<int>> 
{ 
    private const int CouldBeAnyConstant = 392; 

    public override bool Equals(object other) 
    { 
     return Equals((ComparableDictionary)other); 
    } 

    public bool Equals(ComparableDictionary other) 
    { 
     return other != null && (GetHashCode() == other.GetHashCode()); 
    } 

    public override int GetHashCode() 
    { 
     int result = CouldBeAnyConstant; 
     unchecked 
     { 
      foreach (var list in Values) 
       foreach (var value in list) 
        result = result*value.GetHashCode(); 

      foreach (var value in Keys) 
       result = result * value.GetHashCode(); 
     } 

     return result; 
    } 

}

然後,所有你需要做的使用它是:

public bool UserHasMadeChanges(ComparableDictionary Origins, ComparableDictionary Changes) 
{ 
    return !Origins.Equals(Changes) 
} 
0

由保羅·魯安和matmot啓發我開發我自己的方式:

foreach (var change in this.Changes) 
     { 
      List<int> origin = this.Origins[change.Key]; 

      List<int> newValue = change.Value; 

      //find the basic add and remove 
      IEnumerable<int> remove = origin.Except(newValue); 
      IEnumerable<int> add = newValue.Except(origin); 

      if (!add.Any() && remove.Any()) 
      { 
       //remove all in the remove list 
       continue; 

      } 
      else if (add.Any() && !remove.Any()) 
      { 
       //add all in the add list 
       continue; 
      } 

      //if in the same change there are add and remove 
      IEnumerable<int> dif1 = add.Except(remove); 
      IEnumerable<int> dif2 = remove.Except(add); 

      if (dif1.Any()) 
      { 
       //add all in the dif1 list 

      } 
      if (dif2.Any()) 
      { 
       //remove all in dif2 list 


      } 
     } 

你認爲怎麼樣這個 ?

+0

當您嘗試從不存在的「起源」中檢索值時,即在對新密鑰添加值時,它會拋出。 –

+0

此外,您似乎在IEnumerable '上使用了名爲'IsNullOrEmpty'的擴展方法。但是,由於Enumerable.Except()不會返回null,因此值不會被視爲null。因此,您可以使用現有的'Enumerable.Any()'擴展方法來檢查是否有任何元素。 –

+0

@Paul Ruane。Enumerable.Any()的好點,我會編輯我的帖子。 但是,在我的情況下,起源包含所有可能的關鍵。 這是一個很好的評論。謝謝 –