c# – 查找出现在所有列表(或数组或集合)中的值
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 查找出现在所有列表(或数组或集合)中的值,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3364字,纯文字阅读大概需要5分钟。
内容图文
![c# – 查找出现在所有列表(或数组或集合)中的值](/upload/InfoBanner/zyjiaocheng/763/ba02560b8e6f45cbb18528dfb1e68959.jpg)
鉴于以下内容:
List<List<int>> lists = new List<List<int>>();
lists.Add(new List<int>() { 1,2,3,4,5,6,7 });
lists.Add(new List<int>() { 1,2 });
lists.Add(new List<int>() { 1,2,3,4 });
lists.Add(new List<int>() { 1,2,5,6,7 });
确定所有列表中出现哪些数字的最佳/最快方法是什么?
解决方法:
要为两个列表执行此操作,可以使用x.Intersect(y).
要做好几个我们想要做的事情,如:
var intersection = lists.Aggregate((x, y) => x.Intersect(y));
但这不起作用,因为lambda的结果不是List< int>因此无法反馈.这可能会诱使我们尝试:
var intersection = lists.Aggregate((x, y) => x.Intersect(y).ToList());
但是这会对ToList()进行n-1个不必要的调用,这相对来说比较昂贵.我们可以解决这个问题:
var intersection = lists.Aggregate(
(IEnumerable<int> x, IEnumerable<int> y) => x.Intersect(y));
这适用于相同的逻辑,但是在lambda中使用显式类型时,我们可以将Intersect()的结果反馈回来,而不会浪费时间和内存,每次都创建一个列表,因此可以提供更快的结果.
如果这出现了很多,我们可以通过滚动我们自己而不是使用Linq来进一步(轻微)性能改进:
public static IEnumerable<T> IntersectAll<T>(this IEnumerable<IEnumerable<T>> source)
{
using(var en = source.GetEnumerator())
{
if(!en.MoveNext()) return Enumerable.Empty<T>();
var set = new HashSet<T>(en.Current);
while(en.MoveNext())
{
var newSet = new HashSet<T>();
foreach(T item in en.Current)
if(set.Remove(item))
newSet.Add(item);
set = newSet;
}
return set;
}
}
这假定它仅供内部使用.如果它可以从另一个程序集调用它应该有错误检查,也许应该定义,以便只对调用代码的第一个MoveNext()执行交叉操作:
public static IEnumerable<T> IntersectAll<T>(this IEnumerable<IEnumerable<T>> source)
{
if(source == null)
throw new ArgumentNullException("source");
return IntersectAllIterator(source);
}
public static IEnumerable<T> IntersectAllIterator<T>(IEnumerable<IEnumerable<T>> source)
{
using(var en = source.GetEnumerator())
{
if(en.MoveNext())
{
var set = new HashSet<T>(en.Current);
while(en.MoveNext())
{
var newSet = new HashSet<T>();
foreach(T item in en.Current)
if(set.Remove(item))
newSet.Add(item);
set = newSet;
}
foreach(T item in set)
yield return item;
}
}
}
(在这最后两个版本中,如果我们最终清空该套装,则有机会短路,但如果这种情况相对经常发生,它只能得到回报,否则就是净损失).
相反,如果这些不是问题,如果我们知道我们只是想要用列表来做这个,我们可以使用Count和索引进一步优化:
public static IEnumerable<T> IntersectAll<T>(this List<List<T>> source)
{
if (source.Count == 0) return Enumerable.Empty<T>();
if (source.Count == 1) return source[0];
var set = new HashSet<T>(source[0]);
for(int i = 1; i != source.Count; ++i)
{
var newSet = new HashSet<T>();
var list = source[i];
for(int j = 0; j != list.Count; ++j)
{
T item = list[j];
if(set.Remove(item))
newSet.Add(item);
}
set = newSet;
}
return set;
}
而且如果我们知道我们总是希望将结果放在列表中,并且我们知道要么我们不会改变列表,要么输入列表变异无关紧要,我们可以针对这种情况进行优化存在零个或一个列表(但如果我们可能不需要列表中的输出,则会花费更多):
public static List<T> IntersectAll<T>(this List<List<T>> source)
{
if (source.Count == 0) return new List<T>(0);
if (source.Count == 1) return source[0];
var set = new HashSet<T>(source[0]);
for(int i = 1; i != source.Count; ++i)
{
var newSet = new HashSet<T>();
var list = source[i];
for(int j = 0; j != list.Count; ++j)
{
T item = list[j];
if(set.Remove(item))
newSet.Add(item);
}
set = newSet;
}
return new List<T>(set);
}
尽管如此,除了使该方法不太广泛适用之外,这在如何使用方面存在风险,因此只有在您知道不会改变输入或输出时才适用于内部代码事后,或者说这无关紧要.
内容总结
以上是互联网集市为您收集整理的c# – 查找出现在所有列表(或数组或集合)中的值全部内容,希望文章能够帮你解决c# – 查找出现在所有列表(或数组或集合)中的值所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。