c# - 如何循环遍历 n 维稀疏矩阵(由自己的类创建)?
问题描述
我有两节课
class CSparseMatrix:
{
public int NumberOfDimensions { get; set;}
public int DefaultNumber { get; set; }
List<int> dimensionsRanges = new List<int>(); // that's specify dimension of ranges, f.e. {100, 100, 100, 120..}
List<CSparseCell> cells = new List<CSparseCell>(); // contains only values different from default for this matrix
}
class CSparseCell {
public int Value { get; set; }
public List<int> coordinates = new List<int>();
}
问题是:如何循环CSparseMatrix
并输出所有范围的值,格式如下:[0, 0, 0, 0] - *value*, [0, 0, 0, 1] - *value*, [0, 0, 0, 2] - *value*, ...[dimensionsRanges[0]-1, dimensionsRanges[1]-1, dimensionsRanges[2]-1, dimensionsRanges[3]-1] - *value*
所以通过所有范围并输出所有值(我们可以有任意数量的这种维度)。这意味着在程序中我们必须输出矩阵的所有值,它可以有任意数量的维度和范围可以不同。但是我们不知道这个维数是多少,所以不能使用 n 嵌套循环,实际上我不知道如何迭代所有值的算法或方法List<int> dimensionsRanges
我们从这个“矩阵”中得到具体值的方式是
public int GetValueFromCell(List<int> coordinate)
{
foreach(CSparseCell cell in cells)
{
if(cell.coordinates.All(coordinate.Contains)) {
return cell.Value;
}
}
return DefaultNumber;
}
解决方案
既然您说您的矩阵很大,请避免CSparseCell
通过将Value
查找推送到答案计算来返回。
您创建一个方法来返回稀疏矩阵中的所有坐标,使用辅助方法来增加坐标。注意:我将坐标增量方法更改为使用for
循环,而不是do
更容易理解(?)。
void IncCoord(ref List<int> aCoord) { // ref not needed, just for documentation
for (var curDim = NumberOfDimensions - 1; curDim >= 0; --curDim) {
if (aCoord[curDim] == dimensionsRanges[curDim] - 1) // handle carry
aCoord[curDim] = 0;
else {
++aCoord[curDim];
break;
}
}
}
public IEnumerable<List<int>> AllCoords() {
var curCellCoord = Enumerable.Repeat(0, NumberOfDimensions).ToList();
var numCells = dimensionsRanges.Product();
for (int j1 = 0; j1 < numCells; ++j1) {
yield return curCellCoord.ToList();
IncCoord(ref curCellCoord);
}
}
现在您可以使用此方法获取所有Value
s 并且您可以根据需要格式化输出。假设t
是CSparseMatrix
:
var ans = t.AllCoords().Select(c => $"[{c.Join(",")}] - {t.GetValueFromCell(c)}");
使用了几个辅助扩展方法:
public static class IEnumerableExt {
public static int Product(this IEnumerable<int> src) => src.Aggregate(1, (a,n) => a * n);
}
public static class StringExt {
public static string Join<T>(this IEnumerable<T> items, string sep) => String.Join(sep, items);
}
推荐阅读
- javascript - 使用 Node HTTP 模块写入 HTTP 响应的“文本”属性
- sql - 从表中选择列值具有“最高优先级”的行
- css - Sass 不导入角度材质复选框主题
- java - Sqlite 数据库:ID 不会在 android 中自动递增
- javascript - 从打字稿对象中查找具有填充值的属性名称
- c++ - 如何为 QListIterator 使用声明自定义 typedef
- python-3.x - 更改列表中的对象变量
- mongodb - 如何使用 AWS DocDb 配置 Symfony?
- devise - Rails 设计忘记密码,发送令牌,但密码更改失败
- react-native - 无法从“node_modules/expo/AppEntry.js”解析“../../App”