1

我有 2 个结构相似的字典

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};

用户操作后,我将更改保留在 Changes 字典中。基本上,用户可以添加或删除一些链接到字符串的数字。所以我保留了这样的任何变化的所有痕迹:

示例:如果用户在字典中的“tata”中添加 1 更改 a 有“tata”有 1

如果用户在字典中的“toto”中添加 4 更改 a 有“toto”有 1,2,3,4

如果用户在字典中删除“titi”中的 1 更改 a 有“titi”有 2

我需要更改字典来了解用户何时返回原始状态,并进行简单的比较。

如果没有对字符串进行任何更改,则 Changes 字典没有该字符串的任何条目。

多次更改后,用户可以保存更改。所以现在我需要找到所有的添加和删除操作。

我的第一个想法是比较两个字典,看看添加操作和删除操作。但是如何?如果我比较相同字符串的列表,我可能知道区别,但我被困在这里。也许有更好的方法来做到这一点?有什么建议吗?

4

4 回答 4

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),您需要迭代字典并比较 Changes with 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

如果您需要做的就是确定两个对象是否相等,我建议您创建自己的类,并覆盖Equals()and 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 回答
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 回答