2010-12-16 42 views
11
var nums = new[]{ 1, 2, 3, 4, 5, 6, 7}; 
var pairs = /* some linq magic here*/ ; 

=> 雙= {{1,2},{3,4},{5,6},{7,0}}LINQ到對象 - 返回對數從號碼列表

pairs元素應該是兩個元素的列表,或者一些匿名的類的實例有兩個領域,像new {First = 1, Second = 2}

+1

問題完全重複自己的http請求://計算器。com/questions/3575925/linq-to-return-all-pairs-of-elements-from-two-lists – 2010-12-16 13:56:26

+0

@Jani不,它不是。這是要求與Python(或Ruby's)Zip()方法等價 - >需要兩個列表並生成一個元組列表。這個問題是關於分割單個列表。 – 2010-12-16 14:03:43

+2

@克里斯蒂得到它,對不起 – 2010-12-16 14:05:14

回答

3

試試這個:

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}); 
+4

你可以做。選擇((n,i)=> ...)得到一個自動計數器 – 2010-12-16 13:52:28

0
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] }); 
+0

-1:這不是他要求的。 – 2010-12-16 13:57:09

+0

這將返回對{{1,2},{2,3},...} – Yakimych 2010-12-16 14:25:01

+0

@Lasse它工作正常,因爲我理解的問題,所以請撤銷你的downvote – 2010-12-16 16:22:51

-1

這給所有可能對(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 p.a Mod 2 <> 0 Select p 

注:最後一對是失蹤,正在工作

編輯:

工會uniquePairs有一對{nums.Last,0}

+0

這不是我要求的。 – 2010-12-16 14:01:50

+0

我沒有注意到這些對在seuqence。我編輯了答案 – 2010-12-16 14:21:56

1

這可能是有點更普遍比你需要 - 你可以設置自定義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(); 
+0

酷!一個警告,如果數字列表有奇數,成對的最後一項只有1個元素。例如。 nums = {1,2,3} => pairs = {{1,2},{3}} – 2010-12-16 14:15:29

+0

查看一般情況的更新。如果你只需要每組兩個項目,那麼你可以對'nums.Count()'做一個簡單的檢查,如果它是奇數,可以追加一個'0'。 – Yakimych 2010-12-16 14:19:27

0
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); 
+0

我會一直添加一個值爲0的元素,如果數字的長度是偶數,它將被自動忽略。 – 2010-12-16 14:21:49

+0

我不知道有一個支持索引的Where()版本。 +1 – 2010-12-16 14:21:51

+0

它也適用於奇數長度的列表:) – 2010-12-16 14:27:17

1

(警告:長得難看)

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); 
+0

從Danny Chen偷竊,你可以在Zip的第二個參數中追加一個'0'元素,從而擺脫你最後的.Concat(...)塊。 – 2010-12-16 14:31:43

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() }; 
7

無默認LINQ方法可以懶洋洋地做到這一點,用一個單一的掃描。使用自己壓縮序列進行2次掃描,分組並不完全是懶惰的。最好的辦法就是直接執行它:

public static IEnumerable<T[]> Partition<T>(this IEnumerable<T> 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; 
} 
+0

看着所有的答案,似乎Linq並不是這裏最好的方法。你的實現很乾淨。 – 2010-12-16 15:08:33

+0

它應該是'公共靜態IEnumerable 分區 ...'。 – 2012-06-28 00:03:37

1
public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max) 
{ 
    return InSetsOf(source, max, false, default(T)); 
} 

public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max, bool fill, T fillValue) 
{ 
    var toReturn = new List<T>(max); 
    foreach (var item in source) 
    { 
     toReturn.Add(item); 
     if (toReturn.Count == max) 
     { 
      yield return toReturn; 
      toReturn = new List<T>(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(); 
0
IList<int> numbers = new List<int> {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<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7}; 
var batched = numbers.Batch(2);