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。但是怎么做呢?
如果我比较同一个字符串的列表,我可能知道区别,但是我被困在这里了。
也许有更好的方法?有什么建议吗?您有以下情况:
更改中
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
}
}