c#-比较两本字典,了解每一本;加上「;操作和每一个“;删除“;操作

c#-比较两本字典,了解每一本;加上「;操作和每一个“;删除“;操作,c#,.net,.net-3.5,dictionary,change-tracking,C#,.net,.net 3.5,Dictionary,Change Tracking,我有两本结构相似的词典 Dictionary<string, List<int>> Origins 字典起源 及 字典更改 我一开始就创造了起源。它是起始状态的副本。 例如: Origins["toto"] = new List<int>(){1,2,3}; Origins["tata"] = new List<int>(); Origins["titi"] = new List<int>(){1,2}; Origins[“to

我有两本结构相似的词典

Dictionary<string, List<int>> Origins
字典起源

字典更改
我一开始就创造了起源。它是起始状态的副本。 例如:

Origins["toto"] = new List<int>(){1,2,3};
Origins["tata"] = new List<int>();
Origins["titi"] = new List<int>(){1,2};
Origins[“toto”]=newlist(){1,2,3};
起源[“塔塔”]=新列表();
起源[“titi”]=新列表({1,2});
在用户操作之后,我将更改保留在changes词汇表中。 基本上,用户可以添加或删除一些链接到字符串的数字。因此,我保留了所有变化的痕迹,如下所示:

示例:如果用户在“tata”中添加1 字典里有变化 “塔塔”有1个

如果用户在“toto”中添加4 字典里有变化 “toto”有1,2,3,4

如果用户删除“titi”中的1 字典里有变化 “提提”有两个

我需要更改措辞,以便知道用户何时返回原始状态,并进行简单的比较

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

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

我的第一个想法是比较这两个词汇表,查看操作add和操作remove。但是怎么做呢? 如果我比较同一个字符串的列表,我可能知道区别,但是我被困在这里了。
也许有更好的方法?有什么建议吗?

您有以下情况:

  • 一个新的字符串键与一些相关值一起添加到
    更改中
  • 现有字符串键的值已更改(添加或删除值)
  • 在案例(1)中,您将在
    Changes
    中有一个在
    Origins
    中不存在的条目。在案例(2)中,这两个项目都有一个条目,但具有不同的值列表

    (我将假设的值是一个数学集合,即特定值只能在其中出现一次,且排序无关紧要。如果不是这样,则必须稍微修改方法。)

    要检测案例(1),您可以找到唯一的密钥:

    IEnumerable<string> newKeys = Changes.Keys.Except(Origins.Keys);
    
    要检测案例(2),您需要迭代字典并将更改中的值集与原始值进行比较。为此,我们将迭代
    Origins
    以获取键和原始值,然后使用
    Changes
    中的键检索项目。(我们将这样做,因为如果我们迭代
    更改
    ,我们可能会得到
    源代码
    中不存在的新的、添加的键,这是我们必须处理的另一种情况。)

    foreach(源代码中的KeyValuePair条目)
    {
    List originsValues=条目.Value;
    列出更改值;
    //在变更中不处理任何键(正如纪尧姆五世所指出的)。
    如果(!Changes.TryGet(entry.Key,out changesValues))changesValues=originsValues;
    IEnumerable removedValues=originsValues.Exception(changesValues);
    IEnumerable addedValues=更改值。除了(原始值);
    //你在这里处理吗
    }
    
    您可以尝试以下方法:

            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);
                    }
                }
            }
    
    Dictionary Origin=newdictionary();
    Origin[“toto”]=新列表(){1,2,3};
    原点[“塔塔”]=新列表();
    来源[“titi”]=新列表(){1,2};
    字典更改=新字典();
    Changes[“toto”]=newlist(){1,2,3,4};
    更改[“tata”]=新列表(){1};
    更改[“titi”]=新列表(){2};
    Dictionary ToRemove=新字典();
    字典ToAdd=新字典();
    foreach(Origin.Keys中的字符串键)
    {
    ToRemove[键]=原点[键];
    ToAdd[键]=更改[键];
    foreach(删除[key]中的int i)
    {
    if(ToAdd[key].Contains(i))//没有变化
    {
    ToAdd[键]。删除(i);
    删除[键]。删除(i);
    }
    }
    }
    
    如果您只需要确定两个对象是否相等,我建议您创建自己的类,并重写
    Equals()
    GetHashInfo()


    受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
    
    
                }
            }
    
    foreach(此.Changes中的变量更改)
    {
    列表原点=this.Origins[change.Key];
    List newValue=change.Value;
    //查找基本的添加和删除
    IEnumerable remove=origin.Except(newValue);
    IEnumerable add=newValue.Except(原点);
    如果(!add.Any()&&remove.Any())
    {
    //删除删除列表中的所有内容
    继续;
    }
    else if(add.Any()&&!remove.Any())
    {
    //在添加列表中添加所有内容
    继续;
    }
    //如果在同一更改中有添加和删除
    IEnumerable dif1=添加.除外(删除);
    IEnumerable dif2=删除。除了(添加);
    if(dif1.Any())
    {
    //将全部添加到dif1列表中
    }
    if(dif2.Any())
    {
    //删除dif2列表中的所有
    }
    }
    

    您对此有何看法?

    列出更改值=更改[entry.Key].Value;这可能会崩溃,因为更改可能没有键“entry.key”添加[key]=Changes[key];这可能会崩溃,因为当您尝试从不存在的
    检索值时,更改可能没有它将抛出的键“key”,即在针对新键添加值的情况下。此外,您似乎正在
    IEnumerable
    上使用名为
    IsNullOrEmpty
    的扩展方法。但是,值不可能是可枚举的
    null
    。Except()
    不会返回null。因此,您可以在此处使用现有的
    Enumerable.Any()
    扩展方法来检查是否存在任何
    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
    }
    
            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);
                    }
                }
            }
    
    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)
    }
    
    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
    
    
                }
            }