检查一个值集合是否包含另一个值
假设我有两个集合如下:
Collection1:“A1”“A1”“M1”“M2”
Collection2:“M2”“M3”“M1”“A1”“A1”“A2”
所有值都是字符串值。 我想知道Collection1中的所有元素是否包含在Collection2中,但我不保证顺序,并且一个集合可能有多个具有相同值的条目。 在这种情况下,Collection2确实包含Collection1,因为Collection2有两个A1,M1和M2。 这是显而易见的方式:在找到匹配项时对两个集合进行排序并弹出值,但我想知道是否有更快更有效的方法来执行此操作。 再次使用初始集合,我无法保证订单或给定值出现的次数
编辑:将集合更改为集合只是为了清除这些不是集合,因为它们可以包含重复值
是的,只要您没有空间受限,就有更快的方法。 (见空间/时间权衡 。)
算法:
只需将Set2中的所有元素插入一个哈希表(在C#3.5中,这是一个HashSet
或者,只需说:
bool isSuperset = new HashSet(set2).IsSupersetOf(set1);
编辑1:
对于那些担心重复的可能性(因此用词不当“设置”)的人来说,这个想法可以很容易地扩展:
只需创建一个新的Dictionary
表示超级列表中每个单词的计数(每次看到现有单词的实例时,将其添加到计数中,如果不是,则添加计数为1的单词)在字典中),然后通过子列表并每次递减计数。 如果字典中存在每个单词, 并且当您尝试递减它时计数从不为零,那么该子集实际上是一个子列表; 否则,你有一个单词的实例太多(或根本不存在),所以它不是一个真正的子列表。
编辑2:
如果字符串非常大并且您关注空间效率,并且一个适用于(非常)高概率的算法适合您,那么请尝试存储每个字符串的散列 。 从技术上讲,它不能保证工作,但它不工作的可能性非常低。
我所知道的最简洁的方式:
//determine if Set2 contains all of the elements in Set1 bool containsAll = Set1.All(s => Set2.Contains(s));
我在HashSet,Intersect和其他Set理论答案中看到的问题是你确实包含重复项,“A set是一个不包含重复元素的集合”。 这是处理重复案例的一种方法。
var list1 = new List { "A1", "A1", "M1", "M2" }; var list2 = new List { "M2", "M3", "M1", "A1", "A1", "A2" }; // Remove returns true if it was able to remove it, and it won't be there to be matched again if there's a duplicate in list1 bool areAllPresent = list1.All(i => list2.Remove(i));
编辑 :我从Set1和Set2重命名为list1和list2以安抚Mehrdad。
编辑2 :评论意味着它,但我想明确声明这确实改变了list2。 如果您将其用作比较或控件但之后不需要内容,则只能这样做。
看看linq。 ..
string[] set1 = {"A1", "A1", "M1", "M2" }; string[] set2 = { "M2", "M3", "M1", "A1", "A1", "A2" }; var matching = set1.Intersect(set2); foreach (string x in matching) { Console.WriteLine(x); }
类似的
string[] set1 = new string[] { "a1","a2","a3","a4","a5","aa","ab" }; string[] set2 = new string[] {"m1","m2","a4","a6","a1" }; var a = set1.Select(set => set2.Contains(set));