[英].Net LINQ - Filter a dictionary using another dictionary
我有兩個相同類型的字典,A 和 B。
Dictionary<string, IEnumerable<object>>
我正在使用對象來表示具有屬性“Id”的復雜類型。
我正在尋找 A 中的所有項目,這些項目都存在於 B 中(使用 Id),但在不同的 key 下。 基本上是判斷一個對象是否移動了鍵。 A 是新字典,B 是舊字典。
有沒有一種合理的方法可以使用 LINQ 來實現這一點? 我希望結果是 A 中滿足條件的所有鍵值對的字典。 提前致謝。
我使用接口 IHasId 來使用 Id 屬性:
public interface IHasId
{
int Id { get; }
}
以及繼承接口的 AAA 類:
public class AAA: IHasId
{
public int Id { get; set; }
}
這是您要查找的 linq:
Dictionary<string, IEnumerable<IHasId>> A = new Dictionary<string, IEnumerable<IHasId>>();
A.Add("111", new List<IHasId> { new AAA { Id = 1 }, new AAA { Id = 2 } });
A.Add("333", new List<IHasId> { new AAA { Id = 3 } });
Dictionary<string, IEnumerable<IHasId>> B = new Dictionary<string, IEnumerable<IHasId>>();
B.Add("111", new List<IHasId> { new AAA { Id = 1 }});
B.Add("222", new List<IHasId> { new AAA { Id = 2 }});
B.Add("333", new List<IHasId> { new AAA { Id = 3 } });
var res = A.Where(a => a.Value.Any(c => B.Any(v => v.Value
.Select(x => x.Id).Contains(c.Id) && a.Key != v.Key))).ToList();
在此示例中,它返回鍵 111,該鍵具有 Id = 2 的對象,該對象從鍵 222 移動到鍵 111
如果您希望將結果作為字典,您可以使用 ToDictionary 更改 ToList:
var res = A.Where(a => a.Value.Any(c => B.Any(v => v.Value
.Select(x => x.Id).Contains(c.Id) && a.Key != v.Key)))
.ToDictionary(a=>a.Key, a=>a.Value);
如果您希望在新字典中僅包含已更改的值,例如示例中的鍵 111 和僅具有 Id = 2 的對象的值,您可以這樣做:
var res = A.Select(a => new KeyValuePair<string, IEnumerable<IHasId>>(a.Key,
a.Value.Where(c => B.Any(v => v.Value.Select(x => x.Id).Contains(c.Id) && a.Key != v.Key))))
.Where(a=>a.Value.Count() > 0)
.ToDictionary(a => a.Key, a => a.Value);
在可搜索性方面,您的字典倒退了; 查找給定字符串的對象是有效的,但您需要能夠查找給定對象的字符串。 用於此目的的有效數據結構是Lookup<object,string>
。
首先,使用ToLookup()創建一個查找表,其中鍵是對象,值是列表 A 和 B 中的鍵列表。使用Union
(而不是Concat
)消除重復項。
var lookup = listA
.Union( listB )
.ToLookup( pair => pair.Value, pair => pair.Key );
一旦你進行了查找,問題就變得微不足道了。
var results = lookup.Where( x => x.Count() > 1);
有關示例數據的工作示例,請參閱此 DotNetFiddle 。
如果您需要帶有原始對象的 A 條目,則可能是:
var result = A.Where(a => B.Any(b => b.Key != a.Key && b.Value.Intersect(a.Value).Any()));
如果您需要 A 條目僅與 B 中的匹配對象,則可能是:
var result = A.Select(a => new KeyValuePair<string, IEnumerable<object>>(a.Key, B.Where(b => b.Key != a.Key).SelectMany(b => b.Value.Intersect(a.Value)))).Where(x => x.Value.Any());
您可以為Intersect
提供自定義相等比較器,以按 Id 或其他方式匹配項目。
如果您需要它作為字典new Dictionary<string, IEnumerable<object>>(result)
請使用new Dictionary<string, IEnumerable<object>>(result)
。
使用 Join 運算符(請參閱join 子句(C# 參考) ):
var dictionary = (
from a in (from entry in A from Value in entry.Value select new { entry.Key, Value })
join b in (from entry in B from Value in entry.Value select new { entry.Key, Value })
on ((dynamic)a.Value).Id equals ((dynamic)b.Value).Id
where a.Key != b.Key
select a
).ToDictionary(a => a.Key, a => a.Value);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.