验证两个列表是否在C#中共享值

时间:2013-07-06 20:19:02

标签: c#-4.0

我想知道两个列表在应用交集之前是否共享值。像 bool DoIntersect(listA,listB)这样的东西真棒!

这是我提出的代码:

// Person is a class with Id and Name properties
List<Person> people1;
List<Person> people2;

// Populate people1 and people2...

// My current solution (pseudocode obviously)...

if (DoIntersect(people1, people2))
{
    people1 = people1.Intersect(people2)
}
else
{
    /* No shared people */
    throw exception;
}

// Continue with the process...

2 个答案:

答案 0 :(得分:2)

这完全取决于你想要的东西:

// are there any common values between a and b?
public static bool SharesAnyValueWith<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
    return a.Intersect(b).Any();
}

对于不重叠的列表,这将每次迭代a和b。对于重叠的列表,这将遍历a,然后通过b迭代,直到找到第一个重叠元素。

// does a contain all of b? (ignores duplicates)
public static bool ContainsAllFrom<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
    return !b.Except(a).Any();
}

这将迭代一次,然后将遍历b,停止在b中的第一个元素而不是a。

// does a contain all of b? (considers duplicates)
public static bool ContainsAllFrom<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
    // get the count of each distinct element in a
    var counts = a.GroupBy(t => t).ToDictionary(g => g.Key, g => g.Count());
    foreach (var t in b) {
        int count;
        // if t isn't in a or has too few occurrences return false. Otherwise, reduce
        // the count by 1
        if (!counts.TryGetValue(t, out count) || count == 0) { return false; }
        counts[t] = count - 1;
    }

    return true;
}

类似地,这将迭代一次,然后将遍历b,停止在b中的第一个元素而不是a。

答案 1 :(得分:1)

我相信如果不改变您使用List的事实,就无法获得更好的性能。

但是,如果您要开始使用 2个排序列表(创建时需要开销),那么您可以使用复杂的O(n)迭代它们,以便了解您是否有共同的价值观。

修改

虽然原始OP没有2个排序列表,但如果有人需要它,这里是在O(n)检查交集的实现:

    public Boolean DoIntersect(SortedList<int,String> listA,SortedList<int,String> listB  )
    {
        if (listA == null || listA.Count == 0 || listB == null || listB.Count == 0)
        {
            return false;
        }
        var keysA = listA.Keys;
        var keysB = listB.Keys;
        int i = 0, j = 0;
        while (i < listA.Count && j < listB.Count)
        {
            if (keysA[i] < keysB[j])
            {
                i++;
            }else if (keysA[i] > keysB[j])
            {
                j++;
            }
            else
            {
                return true;
            }
        }

上面的方法也可以用于IEnumerable列表,只要它们被排序,稍有变化 - 使用GetEnumerator并迭代它。