代码之家  ›  专栏  ›  技术社区  ›  Caspar Kleijne

检查集合中的所有项是否具有相同的值

  •  10
  • Caspar Kleijne  · 技术社区  · 14 年前

    名为MeasurementCollection的集合上的扩展方法检查属性模板.频率每个项的(枚举)具有相同的值。

    public static bool IsQuantized(this MeasurementCollection items)
    {
        return  (from i in items 
                 select i.Template.Frequency)
                .Distinct()
                .Count() == 1;
    }
    

    有关基础类的信息

    MeasurementCollection : ICollection<IMeasurement>
    
    IMeasurement 
    {
        IMeasurementTemplate Template { get; }        
        ......
    }
    

    这是一个正确的方法还是Linq中已经有了一个更简单的解决方案?

    7 回复  |  直到 5 年前
        1
  •  8
  •   Henk Holterman    14 年前

    编辑:为了解决Timwi对3位普查员的担忧:

    bool same = <your default> ;
    var first = items.FirstOrDefault();
    if (first != null)  // assuming it's a class
    {
       same = items.Skip(1).All(i => i.Template.Frequency == first.Template.Frequency); 
    }
    

    它仍然使用2个枚举器。不是一般人的问题 List<> ,但对于DB查询,使用可读性较差的:

    bool same = <your default> ;
    Item first = null;
    
    foreach(var item in items)
    {
        if (first == null)
        {
            first = item;
            same = true;
        }
        else
        {
            if (item.Template.Frequency != first.Template.Frequency)
            {
               same = false;
               break;
            }
        }
    }
    
        2
  •  9
  •   Christoph Jonathan    5 年前

    您只需找到第一个值并检查其他值是否不同,这将避免评估整个集合(除非单个不同的值是最后一个)

    public static bool IsQuantized(this MeasurementCollection items)
    {
        if(!items.Any())
            return false; //or true depending on your use case
    
        //might want to check that Template is not null, a bit a violation of level of demeter, but just an example
        var firstProp = items.First().Template.Frequency;
    
        return !items.Any(x=> x.Template.Frequency != firstProp);
    
    }
    
        3
  •  4
  •   Rune FS    14 年前

    首先是一般的林克建议。如果只是想知道集合中是否正好有一个,请使用Single()或SingleOrDefault()。Count可能会迭代整个集合,这超出了您的需要,因为如果有两个集合,您可以退出。

    public static bool IsQuantized(this MeasurementCollection items)
            {
                var first = items.FirstOrDefault();
                return first != null && items.Skip(1).All(i => first.Template.Frequency == i.Template.Frequency));
            }
    
        4
  •  3
  •   Rune FS    13 年前

    我得到了一些灵感,想到了一个只有速度的解决方案。这真的不是那么可读(我通常更喜欢),但当谈到速度的特点应该是相当不错的。

    对于大多数其他实现O(n)来说,最坏的情况是相同的,但这是不太可能的,因为它要求所有元素的前半部分相等 下半部分全部等于但不等于上半部分的值。 需要与线性搜索相同数量的比较。 在值成对的情况下。因此,项[0]==项[1] 项目[2]==项目[3] 项目[0]!=第[2]项(及类似项),则线性搜索将更快。 一般来说,对于随机数据或少量奇数,这应该比线性搜索快

    public static bool AllSame<T>(this IEnumerable<T> source,
                                  IEqualityComparer<T> comparer = null)
            {
                if (source == null)
                    throw new ArgumentNullException("source cannot be null.", "source");
    
                if (comparer == null)
                    comparer = EqualityComparer<T>.Default;
                var enumerator = source.GetEnumerator();
    
                return source.Zip(comparer);
            }
    
            private static bool Zip<T>(this IEnumerable<T> sequence, IEqualityComparer<T> comparer)
            {
                var result = new List<T>();
                var enumerator = sequence.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    var first = enumerator.Current;
                    result.Add(enumerator.Current);
                    if (enumerator.MoveNext())
                    {
                        if (!comparer.Equals(first, enumerator.Current))
                        {
                           return false;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                return result.Count == 1 ? true : result.Zip(comparer);
            }
    

        5
  •  2
  •   Ivan Ferić    14 年前

    这样会更快:

    public static bool IsQuantized(this MeasurementCollection items)
    {
        if(items == null || items.Count == 0)
           return true;
    
        var valueToCompare = items.First().Template.Frequency;
    
        return items.All(i => i.Template.Frequency == valueToCompare);
    }
    

    它将在第一个项的模板频率不同时返回false,而在代码中,算法将传递整个集合。

        6
  •  0
  •   Tod    10 年前

    我是这样做的:

    public static bool Same<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            var val = source.Select(keySelector).FirstOrDefault();
    
            return source.Select(keySelector).All(a => Object.Equals(a, val));
        }
    

    用途:

    ddlStatus.AppendDataBoundItems = true;
    ddlStatus.Items.Add(new ListItem("<Mixed>", "-1"));
    ddlStatus.DataSource = ctx.Status.OrderBy(s => s.AssetStatus).ToList();
    ddlStatus.DataTextField = "AssetStatus";
    ddlStatus.DataValueField = "id";
    ddlStatus.SelectedValue = Assets.Same(a => a.AssetStatusID) ? Assets.FirstOrDefault().AssetStatusID.ToString() : "-1";
    ddlStatus.DataBind();
    

    这是一个带有可用状态列表的下拉框。表单编辑多个资源。下拉列表需要知道所有资产的价值是否相同。我的分机也是这么做的。

        7
  •  0
  •   Kirill Lutsenko    8 年前

    我建议以下解决方案:

    private static bool IsSameCollections(ICollection<> collection1, ICollection<> collection2)
            {
              return collection1.Count == collection2.Count &&
         (collection1.Intersect(collection2).Count() == collection1.Count);
            }