将一个二维浮点数数组转换为布尔类型

3

假设我有一个二维浮点数数组

float [,] myfloats = new float[10, 10]
FillWithValues(myfloats);

我该如何使用随机评估方法将这个二维浮点数数组转换为一个二维布尔数组?
我希望可以做到以下这样:
bool[,] mybools;
mybools = myfloats.Select(myfloat => Evaluate(myfloat));

但这并不起作用...


我希望有一种映射方法,使它更加优雅。但如果这是你的答案,请发布代码 :) 我不确定如何循环遍历二维数组.. - Enrique Moreno Tent
请参考@Jon Skeet的答案,这应该有助于理解为什么"更加优雅"的方法缺失:https://dev59.com/IXVC5IYBdhLWcg3wfxQ8 - blins
2个回答

3

很遗憾,多维数组与LINQ不兼容且难以处理。我认为没有绕过这个双循环解决方案的方法:

bool[,] mybools = new bool[myfloats.GetLength(0), myfloats.GetLength(1)];
for (int x = 0; x<myfloats.GetLength(0); x++)
    for(int y=0; y<myfloats.GetLength(1); y++)
        mybools[x,y] = Evaluate(myfloats[x,y]);

Array.GetLength(Int32)方法可以返回数组在特定维度上的大小。


1
“虽然不是特别高效,但是使用两种扩展方法,您可以做到这一点:”
var floats = new float[3, 3] {
   { 1f, 2f, 3f },
   { 4f, 5f, 6f },
   { 7f, 8f, 9f }
};

Func<float, bool> floatToBool = f => f > 5f;

var bools =
   floats
   .ToJaggedArray()
   .Select(array => array.Select(floatToBool).ToArray())
   .ToArray()
   .To2DArray();

请注意,您需要将其操作回“数组的数组”才能返回到2D数组。
如果我们将其转换为可枚举的嵌套集合而不是锯齿状数组,它将工作得更好。然后它可能看起来像这样:
var bools =
   floats
   .ToEnumerableOfEnumerables()
   .Select(array => array.Select(floatToBool))
   .To2DArray();

第一部分的两个扩展方法大概是这样的:
[Pure, NotNull]
public static T[][] ToJaggedArray<T>([NotNull] this T[,] p2DArray) {
   var height = p2DArray.GetLength(0);
   var width = p2DArray.GetLength(1);

   var result = new T[height][];

   for (var row = 0; row < height; row++) {
      result[row] = new T[width];
      for (var col = 0; col < width; col++)
         result[row][col] = p2DArray[row, col];
   }

   return result;
}

[Pure, NotNull]
public static T[,] To2DArray<T>([NotNull] this T[][] pJaggedArray) {
   if (!pJaggedArray.Any() || !pJaggedArray[0].Any())
      return new T[0, 0];

   var height = pJaggedArray.Length;
   var width = pJaggedArray[0].Length;

   var result = new T[height, width];
   for (var r = 0; r < height; r++) {
      var subArray = pJaggedArray[r];
      if (subArray == null || subArray.Length != width)
         throw new InvalidOperationException("Jagged array was not rectangular.");

      for (var c = 0; c < width; c++)
         result[r, c] = subArray[c];
   }

   return result;
}

第二部分大致如下:

And for the second part are something like this:

[Pure, NotNull]
public static IEnumerable<IEnumerable<T>> ToEnumerableOfEnumerables<T>(
   [NotNull] this T[,] p2DArray
) {
   var height = p2DArray.GetLength(0);

   for (var row = 0; row < height; row++)
      yield return p2DArray.GetPartialEnumerable(row);
}

[Pure, NotNull]
public static IEnumerable<T> GetPartialEnumerable<T>(
   [NotNull] this T[,] p2DArray,
   int pRow
) {
   var width = p2DArray.GetLength(1);

   for (var col = 0; col < width; col++)
      yield return p2DArray[pRow, col];
}

[Pure, NotNull]
public static T[,] To2DArray<T>(
   [NotNull] this IEnumerable<IEnumerable<T>> pJaggedArray
) {
   if (!pJaggedArray.Any() || !pJaggedArray.First().Any())
      return new T[0, 0];

   var height = pJaggedArray.Count();
   var width = pJaggedArray.First().Count();

   var result = new T[height, width];
   var r = 0;
   foreach (var subArray in pJaggedArray) {
      if (subArray == null || subArray.Count() != width)
         throw new InvalidOperationException("Jagged array was not rectangular.");

      var c = 0;
      foreach (var item in subArray)
         result[r, c++] = item;

      r += 1;
   }

   return result;
}

呃! :) 你有点想多了:Enumerable.Range(0, n).Select(x => Enumerable.Range(0, m).Select(y => (stuff[x, y] = (x * y)) > 10).ToArray()).ToArray(); - 你可以通过这种方式既返回新数组,又将值分配给现有数组(建议使用ToList()/ToArray()来实际执行可枚举)。当然,返回类型将是[n][m],而不是[n,m],因为在这种情况下不应使用LINQ ;) - PTwr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接