C# 按键比较两个字典,并创建一个新字典,其中键不’;不匹配

C# 按键比较两个字典,并创建一个新字典,其中键不’;不匹配,c#,C#,我有两本类型的字典(string,string)。我需要比较这些,并创建一个新的字典,其中只有键不匹配。例如,给定这些值 Dictionary A Key Value ========= A B C D Dictionary B Key Value ========= A Z E D 我需要创建一个新字典,它只有一个条目(E,D) ==编辑==== 当比较完成时,我只是涉及到键,值是不感兴趣的。键值只是字符串,所以不要链接到其他对象。没有隐藏

我有两本类型的字典(string,string)。我需要比较这些,并创建一个新的字典,其中只有键不匹配。例如,给定这些值

Dictionary A

Key  Value
=========
A      B
C      D


Dictionary B

Key  Value
=========
A      Z
E      D
我需要创建一个新字典,它只有一个条目(E,D)

==编辑====


当比较完成时,我只是涉及到键,值是不感兴趣的。键值只是字符串,所以不要链接到其他对象。没有隐藏的映射等。只有当我有结果字典时,“值”才会起作用,因为这会在我的程序中使用。把这个问题想象成值不存在,我只是想得到字典“B”中的键列表,但不在字典“a”中。我对键“C”不感兴趣,因为我只对字典“B”中的唯一键感兴趣,而不在字典“a”中“

要创建包含
B
的所有元素的字典,其键不在
a

var C = B.Where(x => !A.ContainsKey(x.Key))
         .ToDictionary(x => x.Key, x => x.Value);
如果要创建包含
B
所有元素的字典,其值在
a
中,但其键与
a
的相应值不匹配,则可以使用以下方法:

var C = 
    (from a in A
     join b in B on a.Value equals b.Value
     where a.Key != b.Key
     select b)
    .ToDictionary(x => x.Key, x => x.Value);
但是请注意,如果
A
包含具有两个或多个键的相同值,例如
(A,B)
(C,D)
(F,D)
,则此操作将失败。要解决此问题,您可以执行以下操作:

var C = 
    (from a in A
     group a by a.Value into g
     let a = g.First()
     join b in B on a.Value equals b.Value
     where a.Key != b.Key
     select b)
    .ToDictionary(x => x.Key, x => x.Value);
// sample data
Dictionary<string, string> a = new Dictionary<string, string>();
a.Add("A", "B"); a.Add("C", "D");
Dictionary<string, string> b = new Dictionary<string, string>();
b.Add("A", "Z"); b.Add("E", "D");

// first, reverse dictionary A for simplicity
// to quickly get the key for a value
var revA = a.ToDictionary(kv => kv.Value, kv => kv.Key);

// and then compute the result
var result = b.Where(kv => revA.ContainsKey(kv.Value) && revA[kv.Value] != kv.Key)
              .ToDictionary(kv => kv.Key, kv => kv.Value);

那么您只想添加第二个字典中不在第一个字典中的条目,反之亦然

var dictC = dictB.Keys.Except(dictA.Keys)
    .ToDictionary(bKey => bKey, bKey => dictB[bKey]);
如果您也想要相反的结果,您可以在匿名类型上使用
Concat

var dictC = dictB.Keys.Except(dictA.Keys)
    .Select(bKey => new{ Key=bKey, Value=dictB[bKey] })
    .Concat(dictA.Keys.Except(dictB.Keys)
    .Select(aKey => new{ Key=aKey, Value=dictA[aKey] }))
    .ToDictionary(kv => kv.Key, kv => kv.Value);

这里不可能有重复的键,因为第一个查询查找dictionary-1中不在另一个中的键,而第二个查询查找相反的键。因此,使用
Concat
ToDictionary

似乎需要字典
B
中的键值对,其中字典
A
具有不同的键值。在这种情况下,我会这样做:

var C = 
    (from a in A
     group a by a.Value into g
     let a = g.First()
     join b in B on a.Value equals b.Value
     where a.Key != b.Key
     select b)
    .ToDictionary(x => x.Key, x => x.Value);
// sample data
Dictionary<string, string> a = new Dictionary<string, string>();
a.Add("A", "B"); a.Add("C", "D");
Dictionary<string, string> b = new Dictionary<string, string>();
b.Add("A", "Z"); b.Add("E", "D");

// first, reverse dictionary A for simplicity
// to quickly get the key for a value
var revA = a.ToDictionary(kv => kv.Value, kv => kv.Key);

// and then compute the result
var result = b.Where(kv => revA.ContainsKey(kv.Value) && revA[kv.Value] != kv.Key)
              .ToDictionary(kv => kv.Key, kv => kv.Value);
//示例数据
字典a=新字典();
a、 添加(“a”、“B”);a、 添加(“C”、“D”);
字典b=新字典();
b、 添加(“A”、“Z”);b、 添加(“E”、“D”);
//首先,为了简单起见,将字典倒过来
//快速获取值的键
var revA=a.ToDictionary(千伏=>千伏值,千伏=>千伏键);
//然后计算结果
var结果=b,其中(kv=>revA.ContainsKey(kv.Value)&&revA[kv.Value]!=kv.Key)
.ToDictionary(千伏=>千伏键,千伏=>千伏值);

当然,这是假设我们不能从同一个字典中的不同键映射一个值。也就是说,我们不能将例如
(A=>B)
(C=>B)
放在同一个词典中。我认为这在你的问题中暗含真实性。

在这种情况下,(C,D)会发生什么?换句话说,您是否只需要字典B中键与字典A中的项不匹配的项?我们是否可以假设某个值没有从同一字典中的不同键映射?也就是说,我们不能将例如
(A=>B)
(C=>B)
放在同一本词典中?这个问题不够精确,无法给出正确的答案。@DanJ,是的,我只想要词典“B”中的条目。谁的钥匙没有出现在词典“A”中?Jocke,我已经为我的问题添加了更多信息。希望现在更清楚。这看起来也是一个很好的方法。我很好奇哪个解决方案会更快。这看起来不对:我认为OP想要(E,D),因为
D
在字典A中的另一个键下。@dasblinkenlight:嗯,也许吧。但是,如果一个值具有匹配的键,而另一个值不具有匹配的键,那么重复值会发生什么情况呢?问题不太清楚。在OP回复Dan J的评论之前,我不能说:-(@TimSchmelter:非常感谢你,Tim。你的解决方案对我很有效。你救了我:)非常感谢。这看起来不对:我认为OP想要(E,D),因为
D
在字典A中的另一个键下。@dasblinkenlight我不确定
D
是一个值,但OP声明“创建一个新的字典,其中只有键不匹配”。这正是让我认为他想要键不匹配但值匹配的对(见Dan J的评论)。@dasblinkenlight我想这可能是OP想要的。我已经提供了一个解决方案,在这种情况下也应该有效。谢谢你的帮助。我想我最初的问题不太清楚,但你解释正确,给出了多种解决方案。还要感谢Tim Schmelter,他也给出了很好的答案。