我正在寻找一种简洁的方法来处理.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解决方案。
答案 0 :(得分:4)
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。
答案 1 :(得分:1)
的LINQ!全外连接:
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);
}
}
答案 2 :(得分:0)
这些扩展方法将使您能够枚举每个可能的对(遵循您链接到的旧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);
}
}