2013-09-28 36 views
1

这是2D阵列:取(X,Y),其中条件匹配

int[][] array2D = new int[7][]; 
for (int i = 0; i < 7; i++) 
    array2D[i] = new int[7]; 

如何可以把以下到LINQ查询,或者使用可枚举的方法来实现相同的输出?

var lst = new List<Point>(); 

for (int r = 0; r < array2D.Length; r++) 
    for (int c = 0; c < array2D[r].Length; c++) 
     if (array2D[r][c] == 0) 
      lst.Add(new Point(c, r)); 

编辑 - 基于解决方案@“王中王的回答

var lst = m_boardArr.SelectMany((row, rowIndex) => 
      row.Select((val, colIndex) => 
       new { val, point = new Point(colIndex, rowIndex) }) 
        .Where(col => col.val == 0) 
        .Select(col => col.point)).ToList(); 

回答

1

试试这个:

var lst = array2D.SelectMany((x,r) => x.Select((a,c)=> new {a,b=new Point(c,r)}) 
             .Where(a=>a.a==0) 
             .Select(a=>a.b)).ToList(); 
+0

这将不起作用:c循环变量在已过滤的行上运行,并且不会反映原始数组的索引。 – CSJ

+0

@CSJ你说得对,有点小错。 –

+1

大量的编辑,但你最终得到它:)这是最紧凑的答案。我喜欢这个。 – Nayan

1
var lst = array2D 
    .SelectMany((innerArray, r) 
     => Enumerable 
       .Range(0, innerArray.Length) 
       .Where(c => innerArray[c] == 0) 
       .Select(c => new Point(c, r))) 
    .ToList(); 

不过,您目前的解决方案是更具可读性。

+0

您的第一个答案有效,但第二个答案不可编,因为Point是结构,而不是类。所以,你不能输入一个null来指向Point。谢谢! – Nayan

+0

@Nayan对。我删除了错误的版本。 – BartoszKP

1

诀窍是使用SelectSelectMany可捕捉到循环变量到匿名类型,然后让这些属性回来以后Where条款之后,即:

var list = array2D 
    .SelectMany((row, r) => row 
     .Select((el, c) => 
     new {Element = el, ColIndex = c, RowIndex = r}) 
     .Where(thing => thing.Element == 0) 
     .Select(thing => new Point(thing.RowIndex, thing.ColIndex))) 
    .ToList(); 

编辑:Bartosz的评论也适用于此解决方案。不可读!

+0

你的解决方案给出了几乎正确的答案......实际上,你交换了x和y。所以,该列表包含'Point(y,x)'数据。不过,数值是正确的。 – Nayan

+0

我认为'LINQ'在很多情况下是'不可读'的。查询越复杂,我们可以感受到的越难以读懂,也许这是因为它的“简洁”。 –