簡體   English   中英

.Net LINQ - 使用另一個字典過濾字典

[英].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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM