2014-10-20 27 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(); 
相关问题