我有多个类型列表:
public List<KeyValuePair<KeyValuePair<string, string>,
List<KeyValuePair<string, string>>>> rawComparisonObject;
我想根据构造List的KeyValuePair的“键”得到这些列表的交集
我试过了:
List2 = list1.Intersect(list2).Intersect(list3)......
等,但正如你所看到的那样,将所有KeyValuePair变量相互交叉,而不是我想要的变量。
我也试过了 Intersect lists on KeyValuePair key?
以下表格:
public List<List<KeyValuePair<KeyValuePair<string, string>, List<KeyValuePair<string, string>>>>> getCommon(List<ResourceInformation> input)
{
List<List<KeyValuePair<KeyValuePair<string, string>, List<KeyValuePair<string, string>>>>> rawComparisonObject =
new List<List<KeyValuePair<KeyValuePair<string,string>,List<KeyValuePair<string,string>>>>>();
foreach (ResourceInformation item in input)
{
rawComparisonObject.Add(item.rawComparisonObject);
}
foreach (List<KeyValuePair<KeyValuePair<string, string>, List<KeyValuePair<string, string>>>> item in rawComparisonObject)
{
}
List<List<KeyValuePair<KeyValuePair<string, string>, List<KeyValuePair<string, string>>>>> common =
new List<List<KeyValuePair<KeyValuePair<string, string>, List<KeyValuePair<string, string>>>>>();
for (int i = 0; i < (rawComparisonObject.Count-1); i++)
{
var keysFromB = new HashSet<KeyValuePair<string, string>>(rawComparisonObject[i].Select(x => x.Key));
var result = rawComparisonObject[i+1].Where(x => keysFromB.Remove(x.Key));
common.Add(result.ToList());
}
return common;
}
它返回了非常错误的值, 在那儿 有什么简单的方法吗?
我在链接数据工作中使用此数据结构,以便通过比较对象来获取常见对象
Ex:Batman vs. Inception
应该返回:
类型:电影|电影
主演:克里斯蒂安贝尔|莱昂纳多·迪卡普里奥
当然一切都用它的URI链接突出显示,这就是为什么我需要keyValuePair一个用于URI而另一个用于标签....
我尽力解释这个复杂的数据结构。希望它足够清楚
答案 0 :(得分:3)
我理解您编写的代码,这是我的(修订版)翻译:
public List<List<KeyValuePair<KeyValuePair<string, string>, List<KeyValuePair<string, string>>>>> getCommon(List<ResourceInformation> input)
{
var rawComparisonObject =
input.Select(item => item.rawComparisonObject).ToList();
var common = rawComparisonObject.Zip(
rawComparisonObject.Skip(1),
(prevItems, nextItems) =>
(from next in nextItems
join prev in prevItems on next.Key equals prev.Key
select next).ToList()).ToList();
return common;
}
编辑:上面的翻译,在中间省略了空的foreach循环,并使用连接作为过滤器,仅投影通过连接条件的“下一个”元素。我倾向于喜欢加入这种过滤,因为我知道它利用散列下的哈希来有效地执行它的匹配。
我之前版本的问题在于它使用'group join'变量收集了连接结果,这导致了我们不想要的额外枚举。更改后,内部ToList()
类似于帖子中提供的原始代码示例中的result
变量。外ToList()
是结果的最终common
变量(重新)包装。我相信这将提供类似于原始代码的结果;但是,我强烈建议测试验证结果是否符合预期。
GetCommon
更改为这样的通用类型(稍后将其更改回来):
public List<List<KeyValuePair<T, List<T>>>> GetCommon<T>(/*List<ResourceInformation> input*/)
从那里,我们可以将rawComparisonObject
列表提升为方法的参数 - 并且在这样做的过程中,我们将替换方法的当前参数。使用var
键入允许我们避免更改common
局部变量的类型(只要我们小心输出类型与预期的返回类型匹配,这是我原来的错误翻译。)
还有更多的设计理念和问题,而不是我在这里可以轻松地检查,所以我将关闭而不试图这样做。我确实想提出这是一个很好的挑战 - 有时LINQ不是正确的选择,但即使它不是正确的选择,改变方法也可以让它值得尝试。谢谢!
答案 1 :(得分:0)
您可以使用linq执行此操作,但您可能应该更改数据模型以提高效率:
var keys = list1.select( kv => kv.Key).intersection(list2.select(kv => kv.Key)
var result = list1.where( key => keys.contains(key).TolLst()
答案 2 :(得分:0)
如果您只想将KeyValuePairs与其密钥相交,则应实现自定义IEqualityComparer<T>
并使用Intersect()
方法,如下所示:
class KeyValyePairComparer : IEqualityComparer<KeyValuePair<string, string>>
{
public bool Equals(KeyValuePair<string, string> x, KeyValuePair<string, string> y)
{
return x.Key == y.Key;
}
public int GetHashCode(KeyValuePair<string, string> item)
{
return item.Key.GetHashCode();
}
}
使用上面的实现,您可以获得与查询的交集:
var comparer = new KeyValuePairComparer();
var intersection = list1.Intersect(list2, comparer).Intersect(list3, comparer);