2014-10-20 55 views
0

比方說這是我的列表{1,2,3,4,5,6,7,8,9}將項目與Linq混合到一個新列表中

現在我想將這些項目混合到以下列表中:{1,9,2,8,3,7,..}

基本上總是一個項目從左側和一個項目從右側的列表。

是否有可能通過使用linq語句創建它?

回答

0

這裏有一個想法:

var sample = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
var res = sample 
    .Select((z, i) => i % 2 == 0 
     ? sample[i/2] 
     : sample[sample.Count - i/2 - 1]) 
    .ToList(); 

基本上它使用以模爲單位在列表的開始或結束處選擇一個項目。

請注意我甚至沒有使用枚舉的z值,所以雖然LINQ在這裏實際使用,但它不是簡單的for循環。

編輯:

如果你想要的東西,計算速度更快,嘗試一些不LINQ:

int count = sample.Count; 
var res = new List<int>(count); 

for (int i = 0; i < sample.Count; i++) 
{ 
    var iDividedByRwo = i/2; 
    if (i % 2 == 0) 
    { 
     res.Add(sample[iDividedByRwo]); 
    } 
    else 
    { 
     res.Add(sample[count - iDividedByRwo - 1]); 
    } 
} 

編輯2:好了,我做你的工作,但...

private static void Main(string[] args) 
{ 
    var sample = Enumerable.Range(0, 100000).ToList(); 

    var z1 = Stopwatch.StartNew(); 
    for (int i = 0; i < 1000; i++) 
    { 
     Test1(sample); 
    } 

    z1.Stop(); 
    Console.WriteLine(z1.ElapsedMilliseconds); 

    var z2 = Stopwatch.StartNew(); 
    for (int i = 0; i < 1000; i++) 
    { 
     Test2(sample); 
    } 

    z2.Stop(); 
    Console.WriteLine(z2.ElapsedMilliseconds); 

    Console.Read(); 
} 

private static void Test1(IList<int> input) 
{ 
    var res2 = input 
     .Select((z, i) => i % 2 == 0 
      ? input[i/2] 
      : input[input.Count - i/2 - 1]) 
     .ToList(); 
} 

private static void Test2(IList<int> input) 
{ 
    int count = input.Count; 
    var res = new List<int>(count); 

    for (int i = 0; i < input.Count; i++) 
    { 
     var iDividedByRwo = i/2; 
     if (i % 2 == 0) 
     { 
      res.Add(input[iDividedByRwo]); 
     } 
     else 
     { 
      res.Add(input[count - iDividedByRwo - 1]); 
     } 
    } 
} 

結果:

4195 
1136 

如果您想獲得最快的方法,請插入其他方法並比較結果。

1

是的,你可以做到這一點只使用LINQ(相當簡單,甚至是),但它並不完全令人愉快:

  • 反向列表
  • 與原來的名單得到雙拉鍊它( 1,9),(2,8)等
  • 拼合結果
  • 採取只有原來的數

這樣:

var query = original.Zip(original.Reverse(), (x, y) => new[] { x, y }) 
        .SelectMany(x => x) 
        .Take(original.Count()); 

如果我真的要使用此代碼,我肯定把評論在那裏...

+0

自己的答案可能重複:http://stackoverflow.com/a/1758451/3629689;) – clarkitect 2014-10-20 11:53:05

+0

@jeffdot:是的,'Interleave'你可以只使用'original.Interleave(original.Reverse())。拿(original.Count())' – 2014-10-20 11:53:46

+0

謝謝Jon,你可以看看ken2k的答案,並告訴我哪個可能表現更好? – 2014-10-20 11:54:06

0

這裏的另一種方法:

var list = new List<int>{1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
List<int> alternatingOrder = list 
     .Select((i, index) => new 
     { 
      i, 
      Margin = index < list.Count/2 ? index : list.Count - ++index 
     }) 
     .OrderBy(x => x.Margin) 
     .Select(x => x.i) 
     .ToList(); 
相關問題