Linq to Objects – 从数字列表中返回数字对
var nums = new[]{ 1, 2, 3, 4, 5, 6, 7}; var pairs = /* some linq magic here*/ ;
=>对= {{1,2},{3,4},{5,6},{7,0}}
对的元素应该是两元素列表,或者是一些具有两个字段的匿名类的实例,例如new {First = 1, Second = 2}
。
没有任何默认的linq方法可以懒得和单次扫描。 用自身压缩序列会进行2次扫描,并且分组并不完全是懒惰的。 您最好的选择是直接实施它:
public static IEnumerable Partition(this IEnumerable sequence, int partitionSize) { Contract.Requires(sequence != null) Contract.Requires(partitionSize > 0) var buffer = new T[partitionSize]; var n = 0; foreach (var item in sequence) { buffer[n] = item; n += 1; if (n == partitionSize) { yield return buffer; buffer = new T[partitionSize]; n = 0; } } //partial leftovers if (n > 0) yield return buffer; }
试试这个:
int i = 0; var pairs = nums .Select(n=>{Index = i++, Number=n}) .GroupBy(n=>n.Index/2) .Select(g=>{First:g.First().Number, Second:g.Last().Number});
(警告:看起来很难看)
var pairs = x.Where((i, val) => i % 2 == 1) .Zip( x.Where((i, val) => i % 2 == 0), (first, second) => new { First = first, Second = second }) .Concat(x.Count() % 2 == 1 ? new[]{ new { First = x.Last(), Second = default(int) }} : null);
这可能比您需要的更通用 – 您可以设置自定义itemsInGroup
:
int itemsInGroup = 2; var pairs = nums. Select((n, i) => new { GroupNumber = i / itemsInGroup, Number = n }). GroupBy(n => n.GroupNumber). Select(g => g.Select(n => n.Number).ToList()). ToList();
编辑:
如果要在最后一组具有不同大小的情况下附加零(或其他一些数字):
int itemsInGroup = 2; int valueToAppend = 0; int numberOfItemsToAppend = itemsInGroup - nums.Count() % itemsInGroup; var pairs = nums. Concat(Enumerable.Repeat(valueToAppend, numExtraItems)). Select((n, i) => new { GroupNumber = i / itemsInGroup, Number = n }). GroupBy(n => n.GroupNumber). Select(g => g.Select(n => n.Number).ToList()). ToList();
public static IEnumerable> InSetsOf(this IEnumerable source, int max) { return InSetsOf(source, max, false, default(T)); } public static IEnumerable> InSetsOf (this IEnumerable source, int max, bool fill, T fillValue) { var toReturn = new List (max); foreach (var item in source) { toReturn.Add(item); if (toReturn.Count == max) { yield return toReturn; toReturn = new List (max); } } if (toReturn.Any()) { if (fill) { toReturn.AddRange(Enumerable.Repeat(fillValue, max-toReturn.Count)); } yield return toReturn; } }
用法:
var pairs = nums.InSetsOf(2, true, 0).ToArray();
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7 }; var result = numbers.Zip(numbers.Skip(1).Concat(new int[] { 0 }), (x, y) => new { First = x, Second = y }).Where((item, index) => index % 2 == 0);
var w = from ei in nums.Select((e, i) => new { e, i }) group ei.e by ei.i / 2 into g select new { f = g.First(), s = g.Skip(1).FirstOrDefault() };
var nums = new float[] { 1, 2, 3, 4, 5, 6, 7 }; var enumerable = Enumerable .Range(0, nums.Length) .Where(i => i % 2 == 0) .Select(i => new { F = nums[i], S = i == nums.Length - 1 ? 0 : nums[i + 1] });
IList numbers = new List {1, 2, 3, 4, 5, 6, 7}; var grouped = numbers.GroupBy(num => { if (numbers.IndexOf(num) % 2 == 0) { return numbers.IndexOf(num) + 1; } return numbers.IndexOf(num); });
如果你需要填充零的最后一对,你可以在进行分组之前添加它,如果listcount是奇数。
if (numbers.Count() % 2 == 1) { numbers.Add(0); }
另一种方法可能是:
var groupedIt = numbers .Zip(numbers.Skip(1).Concat(new[]{0}), Tuple.Create) .Where((x,i) => i % 2 == 0);
或者您使用具有许多有用扩展的MoreLinq:
IList numbers = new List {1, 2, 3, 4, 5, 6, 7}; var batched = numbers.Batch(2);
这给了所有可能的对(vb.net):
Dim nums() = {1, 2, 3, 4, 5, 6, 7} Dim pairs = From a In nums, b In nums Where a <> b Select a, b
编辑:
Dim allpairs = From a In nums, b In nums Where b - a = 1 Select a, b Dim uniquePairs = From p In allpairs Where pa Mod 2 <> 0 Select p
注意:最后一对丢失,正在处理它
编辑:
联合uniquePairs
与{nums.Last,0}