首页 > 解决方案 > 如何循环遍历 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;
            }

标签: c#loopsmultidimensional-arrayiteration

解决方案


既然您说您的矩阵很大,请避免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);
    }
}

现在您可以使用此方法获取所有Values 并且您可以根据需要格式化输出。假设tCSparseMatrix

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);
}

推荐阅读