在C#中检查所有列表项是否具有相同的成员值

7

我正在寻找一种简单快速的方法来检查我的所有List项是否具有相同成员变量的值。

foreach (Item item in MyList)
{
    Item.MyMember = <like all other>;
}

编辑: 我忘了一件事:如果其中一个成员(是一个字符串)为空,并且所有其他项目都具有相同的字符串,则它也应该为真!对不起,我忘了这点。

6个回答

27

EDIT: Okay, after the new requirement has

bool allSame = !MyList.Select(item => item.MyMember)
                      .Where(x => !string.IsNullOrEmpty(x))
                      .Distinct()
                      .Skip(1)
                      .Any();

这样可以避免您需要先找到一个样本值来开始。(当然,它一旦找到第二个值就会退出。)

它还只遍历序列一次,如果序列不是可重复的,则这可能很重要。如果是List<T>,那么这不是问题。

编辑:为了消除对Skip的担忧,根据文档:

如果包含少于个元素,则返回空的IEnumerable<T>。 如果小于或等于零,则产生的所有元素。


聪明,但我认为如果MyList为空,Skip(1)会抛出异常。 - H H
@Henk:不会的,相信我 :) - Jon Skeet
我忘了一件事:如果其中一个成员(它是一个字符串)是String.Empty,并且所有其他项都具有相同的字符串,则也应为true!抱歉,我忘了这个。 - Sebastian
然后,您只需要在Select和Distinct之间添加Where(item => !string.IsNullOrEmpty(item))(如果要将string.Empty和null字符串视为“通配符”,则可以考虑这些字符串,如果只想考虑空字符串:Where(item => (item != string.Empty) ))。 - vc 74
@XmlmXmlmX:实际上这并不重要,Jon的逻辑同样有效。 - vc 74
显示剩余10条评论

9
您自己的解决方案已经足够简单,但如果您想抽象出循环并且更加清晰地书写代码,您可以使用 Linq。
bool allSame = MyList.All(item => item.MyMember == someValue);

2
当然,这假设你已经知道你要查找的值。 - Jon Skeet
someValue之前是未知的。OP自己的解决方案是原理性的。 - H H
如果你事先没有这个值并且获取它可能很昂贵,那么如果我也会选择Jon的解决方案。 - Anthony Pegram
为什么不只看第一个呢?这会变得有点复杂,因为空字符串会被忽略,但是值是什么并不重要吗?如果它们都需要相同,我们可以假设第一个是正确的值,如果有任何不匹配的,则完成。如果它们全部匹配,则每个值都相等。 - James Hurley

6
using System.Linq;
…

if (myList.Any()) // we need to distinguish between empty and non-empty lists 
{
    var value = myList.First().MyMember;
    return myList.All(item => item.MyMember == value);
}
else
{
    return true;  // or false, if that is more appropriate for an empty list    
}

0

这是一个通用的代码,适用于所有 .NET 版本,从 2.0 开始:

public static bool AllSameByProperty<TItem, TProperty>(IEnumerable<TItem> items, Converter<TItem, TProperty> converter)
{
    TProperty value = default(TProperty);
    bool first = true;

    foreach (TItem item in items)
    {
        if (first)
        {
            value = converter.Invoke(item);
            first = false;
            continue;
        }

        TProperty newValue = converter.Invoke(item); 

        if(value == null)
        {
            if(newValue != null)
            {
                return false;
            } 

            continue;
        }

        if (!value.Equals(newValue))
        {
            return false;
        }
    }

    return true;
}

C# 2.0 中的使用方法:

AllSameByProperty(list, delegate(MyType t) { return t.MyProperty; });

在C# 3.0中的使用:

AllSameByProperty(list, t => t.MyProperty);

如果第一个成员的值为“null”,而第二个成员具有非空值,那么这将产生错误的结果。 - Jon Skeet

-1

我正在这样做:

Item item = MyList.FirstOrDefault(x=>x.MyMember != valueToMatch);
bool allMembersSame = item == null;

-2

我认为这是最短和最优雅的解决方案:

bool allSame = list.GroupBy(item => item.TheProperty).Count == 1;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接