根据键元素的键值对列表的交叉数
本文关键字:列表 键值对 键元 元素 | 更新日期: 2023-09-27 18:31:24
我有很多类型的列表:
public List<KeyValuePair<KeyValuePair<string, string>,
List<KeyValuePair<string, string>>>> rawComparisonObject;
我想根据构造列表的键值对的"键"来获取这些列表的交集
我试过了:
List2 = list1.Intersect(list2).Intersect(list3)......
等,但如您所见,它与所有键值对变量相交,而不是我想要的那个。
我也试过键值对键上的交叉列表?
采用以下形式:
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;
}
它返回了非常错误的值,有吗有什么简单的方法可以做到这一点吗?
我在链接数据工作中使用此数据结构,通过比较对象来获取公共对象
例如:蝙蝠侠大战盗梦空间
应返回:
类型 : 电影 |电影
主演: 克里斯蒂安·贝尔 |莱昂纳多·迪卡普里奥
当然,所有内容都用它的 URI 链接突出显示,这就是为什么我需要 keyValuePair 一个用于 URI,另一个用于标签......
我尽力解释这种复杂的数据结构。 希望足够清楚
据我了解您编写的代码,这是我(修订后的)翻译:
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 循环,并使用连接作为过滤器,仅投影通过连接条件的"next"元素。我倾向于加入这种过滤,因为我知道它利用幕后的哈希来有效地执行它所做的匹配。
我以前的版本的问题在于它使用"组连接"变量收集连接结果,这导致了我们不想要的额外枚举。更改后,内部ToList()
类似于帖子中提供的原始代码示例中的result
变量。外部ToList()
是结果的最终common
变量(重新)打包。我相信这将提供类似于原始代码的结果;但是,我强烈建议进行测试以验证结果是否符合预期。
恕我直言,正确的做法是重构以简化泛型的使用,直到我们可以更好地推理它们。在一次简短的临时尝试中,我将GetCommon
更改为这样的泛型类型(后来将其更改回来):
public List<List<KeyValuePair<T, List<T>>>> GetCommon<T>(/*List<ResourceInformation> input*/)
从那里,我们可以将rawComparisonObject
列表提升为方法的参数 - 在此过程中,我们将替换方法的当前参数。使用 var
类型可以让我们避免更改 common
局部变量的类型(只要我们注意输出类型与预期的返回类型匹配,这对原始翻译来说是不好的。
还有更多的设计想法和问题,我在这里可以舒适地检查,所以我将在不尝试这样做的情况下结束。我确实想提出这是一个很好的挑战 - 有时 LINQ 不是正确的选择,但即使它不是正确的选择,方法的改变也可以使其值得尝试。谢谢!
linq 执行此操作,尽管您可能应该更改数据模型以提高效率:
var keys = list1.select( kv => kv.Key).intersection(list2.select(kv => kv.Key)
var result = list1.where( key => keys.contains(key).TolLst()
如果您只想在键上与 KeyValuePair 相交,则应实现一个自定义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);