代码之家  ›  专栏  ›  技术社区  ›  Hank

按顺序处理每对

  •  4
  • Hank  · 技术社区  · 14 年前

    我正在寻找一种简洁的方法来处理.NET中序列中的每对(无序)元素。 我知道我可以用嵌套 for 循环,但我在寻找一些更可读的东西。

    我在想象一个修改过的 Any() 扩展方法:

    IEnumerable<Transaction> transactions = ...
    if (transactions.AnyPair( (first, second) => first.UniqueID == second.UniqueID))
        throw ...
    

    或者也许 foreach 风格一:

    IEnumerable<JigsawPiece> pieces = ...
    pieces.ForEachPair( (first, second) => {
        TryFit(first, second);
    });
    

    此问题是针对其他语言提出的(例如,请参见 Operation on every pair of element in a list ,但我正在寻找.NET解决方案。

    3 回复  |  直到 14 年前
        1
  •  4
  •   Ian Mercer    14 年前
    var query = transactions
                 .SelectMany((val1,j) => transactions.Select((val2,i) => new {v1=val1, v2=val2, i=i, j=j}))
                 .Where(x => x.i < x.j);
    
    var result = query.Select(x=> x.v1.UniqueID == x.v2.UniqueID);
    

    这将执行正确次数的比较。结果还包括匹配的两个元素的索引i、j。

        2
  •  1
  •   Toby    14 年前

    林克!完全外部联接:

            IEnumerable<JigsawPiece> pieces = new List<JigsawPiece>();
    
            var allPairs =
                from p1 in pieces
                from p2 in pieces
                where !ReferenceEquals(p1, p2)
    
                // edit
                    && pieces.IndexOf(p1) < pieces.IndexOf(p2)
                // endedit
    
                select new { p1, p2 };
    
            foreach (var pair in allPairs)
            {
                TryFit(pair.p1, pair.p2);
            }
    

    编辑以添加实际的扩展方法实现:

        public static void ForEachPair<T>(this IEnumerable<T> source, Action<T, T> action)
        {
            int index = 0;
    
            var dictionary = source.ToDictionary(t => index++);
    
            var distinctPairs =
                from kvp1 in dictionary
                from kvp2 in dictionary
                where kvp1.Key < kvp2.Key
                select new { T1 = kvp1.Value, T2 = kvp2.Value };
    
            foreach (var pair in distinctPairs)
            {
                var copy = pair;
                action(copy.T1, copy.T2);
            }
        }
    
        3
  •  0
  •   Daniel Renshaw    14 年前

    这些扩展方法将使您能够枚举每个可能的对(遵循链接到的旧的so python问题中概述的相同命名/约定),并提供请求的anypair方法和foreachpair方法。

    public static class EnumerableExtensions
    {
        public static bool AnyPair<T>(this IEnumerable<T> values,
            Func<T, T, bool> predicate)
        {
            return values.PairProduct(predicate).Any();
        }
    
        public static void ForEachPair<T>(this IEnumerable<T> values,
            Action<T, T> action)
        {
            foreach (Tuple<T, T> pair in values.PairProduct())
            {
                action(pair.Item1, pair.Item2);
            }
        }
    
        public static void ForEachPair<T>(this IEnumerable<T> values,
            Action<T, T> action, Func<T, T, bool> predicate)
        {
            foreach (Tuple<T, T> pair in values.PairProduct(predicate))
            {
                action(pair.Item1, pair.Item2);
            }
        }
    
        public static IEnumerable<Tuple<T, T>> PairProduct<T>(
            this IEnumerable<T> values)
        {
            return from value1 in values
                   from value2 in values
                   select Tuple.Create(value1, value2);
        }
    
        public static IEnumerable<Tuple<T, T>> PairProduct<T>(
            this IEnumerable<T> values, Func<T, T, bool> predicate)
        {
            return from value1 in values
                   from value2 in values
                   where predicate(value1, value2)
                   select Tuple.Create(value1, value2);
        }
    
        public static IEnumerable<Tuple<T, T>> PairPermutations<T>(
            this IEnumerable<T> values) where T : IComparable<T>
        {
            return from value1 in values
                   from value2 in values
                   where value1.CompareTo(value2) != 0
                   select Tuple.Create(value1, value2);
        }
    
        public static IEnumerable<Tuple<T, T>> PairPermutations<T>(
            this IEnumerable<T> values, IComparer<T> comparer)
        {
            return from value1 in values
                   from value2 in values
                   where comparer.Compare(value1, value2) != 0
                   select Tuple.Create(value1, value2);
        }
    
        public static IEnumerable<Tuple<T, T>> PairCombinations<T>(
            this IEnumerable<T> values) where T : IComparable<T>
        {
            return from value1 in values
                   from value2 in values
                   where value1.CompareTo(value2) < 0
                   select Tuple.Create(value1, value2);
        }
    
        public static IEnumerable<Tuple<T, T>> PairCombinations<T>(
            this IEnumerable<T> values, IComparer<T> comparer)
        {
            return from value1 in values
                   from value2 in values
                   where comparer.Compare(value1, value2) < 0
                   select Tuple.Create(value1, value2);
        }
    }