我有2个字符串列表。 有没有一种简单的方法可以找到一个列表是否包含第二个列表的所有字符串?
(简单地说,我的意思是我没有明确比较一个列表中的每个字符串与所有字符串
答案 0 :(得分:5)
使用Enumerable.Except查找列表之间的差异。如果结果中没有项目,则list2中的所有项目都在list1中:
bool containsAll = !list2.Except(list1).Any();
内部Except
使用Set<T>
从list1
获取唯一商品,并仅返回list2
中未设置的商品。如果没有要返回的内容,那么集合中的所有项目。
答案 1 :(得分:3)
试试这个:
firstList.All(x=>secondList.Contains(x));
较短版本(方法组):
firstList.All(secondList.Contains)
您需要使用Linq编写:
using System.Linq;
它确定了第一个列表中的所有项目都在第二个列表中。 Contains
检查给定项目是否在列表中。如果所有集合项都匹配谓词,则All
给出。给定谓词是:如果项目在第二个列表中,那么整个表达检查所有项目是否在第二个列表中< - 证明有效:)
答案 2 :(得分:3)
对于较大的列表,使用HashSet<T>
(当使用两个列表时,会产生线性Big O,而不是O(n ^ 2)):
var hash = new HashSet<string>(list2);
bool containsAll = list1.All(hash.Contains);
答案 3 :(得分:0)
使用LINQ
bool isSublistOf = list1.All(list2.Contains);
如果IEnumerable
中的每个元素满足lambda中的条件,则All方法返回true。 All将List2的Contains方法作为Func<bool,string>
传递,如果找到该元素List2
,则返回true。实际效果是,如果在List2中找到List1中的所有元素,则该语句返回true。
效果说明
由于All运算符的性质,最坏情况是O(n ^ 2),但是会在第一次机会(任何不匹配)时退出。使用完全随机的8字节字符串,我使用基本的性能工具来尝试每个案例。
static void Main(string[] args)
{
long count = 5000000;
//Get 5,000,000 random strings (the superset)
var strings = CreateRandomStrings(count);
//Get 1000 random strings (the subset)
var substrings = CreateRandomStrings(1000);
//Perform the hashing technique
var start = DateTime.Now;
var hash = new HashSet<string>(strings);
var mid = DateTime.Now;
var any = substrings.All(hash.Contains);
var end = DateTime.Now;
Console.WriteLine("Hashing took " + end.Subtract(start).TotalMilliseconds + " " + mid.Subtract(start).Milliseconds + " of which was setting up the hash");
//Do the scanning all technique
start = DateTime.Now;
any = substrings.All(strings.Contains);
end = DateTime.Now;
Console.WriteLine("Scanning took " + end.Subtract(start).TotalMilliseconds);
//Do the Excepting technique
start = DateTime.Now;
any = substrings.Except(strings).Any();
end = DateTime.Now;
Console.WriteLine("Excepting took " + end.Subtract(start).TotalMilliseconds);
Console.ReadKey();
}
private static string[] CreateRandomStrings(long count)
{
var rng = new Random(DateTime.Now.Millisecond);
string[] strings = new string[count];
byte[] bytes = new byte[8];
for (long i = 0; i < count; i++) {
rng.NextBytes(bytes);
strings[i] = Convert.ToBase64String(bytes);
}
return strings;
}
结果按照以下顺序对它们进行了相当一致的排序:
list1.All(list2.Contains)
)异常方法需要更长时间,因为它需要预先完成所有工作。与其他方法不同,它不会在不匹配时退出,而是继续处理所有元素。散列更快,但在设置散列方面也做了大量工作。这将是最快的方法如果字符串随机性较小且交叉点更加确定。
<强>声明强>
此级别的所有性能调整都是无关紧要的。这只是一项心理锻炼