1

私は類似の構造を持つ2つの辞書を持っています

Dictionary<string, List<int>> Origins

Dictionary<string, List<int>> Changes

最初に Origins を作成しました。初期状態のコピーです。例 :

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

ユーザーの操作の後、変更辞書に変更を保存します。基本的に、ユーザーは文字列にリンクされた数値を追加または削除できます。したがって、次のような変更のすべての痕跡を保持します。

例: ユーザーが辞書の "tata" に 1 を追加した場合 変更 a have "tata" have 1

ユーザーが辞書の「toto」に 4 を追加した場合 変更 a have "toto" have 1,2,3,4

ユーザーが辞書の「titi」の 1 を削除した場合 変更 a have "titi" have 2

ユーザーがいつ元の状態に戻ったかを簡単に比較するには、変更辞書が必要です。

文字列が変更されていない場合、変更辞書にはこの文字列のエントリがありません。

多くの変更の後、ユーザーは変更を保存できます。したがって、すべての追加操作と削除操作を見つける必要があります。

私の最初のアイデアは、2 つの辞書を比較して、操作 add と操作 remove を確認することです。しかし、どのように?同じ文字列のリストを比較すると、違いがわかるかもしれませんが、ここで立ち往生しています。そして、おそらくこれを行うためのより良い方法がありますか? なにか提案を ?

4

4 に答える 4

2

次のケースがあります。

  1. Changesいくつかの関連付けられた値とともに、新しい文字列キーが に追加されます。
  2. 既存の文字列キーの値が変更されます (値が追加または削除されます)。

Changes(1) の場合、 に存在しないエントリがにありOriginsます。(2) の場合、両方にエントリがありますが、値のリストが異なります。

(ここで想定する値は数学的セットです。つまり、特定の値は 1 回しか表示されず、順序付けは重要ではありません。そうでない場合は、アプローチを多少変更する必要があります。)

ケース (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) を検出するには、ディクショナリを反復処理し、Changes の値のセットを Origins と比較する必要があります。これを行うには、反復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
}
于 2011-09-13T21:17:01.430 に答える
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);
                }
            }
        }
于 2011-09-13T21:53:12.783 に答える
0

Paul Ruane と 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


            }
        }

これについてあなたはどう思いますか ?

于 2011-09-14T17:16:48.917 に答える
0

2 つのオブジェクトが等しいかどうかを判断するだけでよい場合は、独自のクラスを作成し、 and をオーバーライドすることをお勧めし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)
}
于 2011-09-14T02:53:59.980 に答える