首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在c#中获取多维数组(指定一维数)的最小和最大值

如何在c#中获取多维数组(指定一维数)的最小和最大值
EN

Stack Overflow用户
提问于 2013-06-11 18:28:05
回答 3查看 175关注 0票数 1

我有一个多维数组ins C#,定义如下:

代码语言:javascript
运行
复制
 double[,,] myArray=new double[10000,10000,3];

例如,当最后一个dim为0时,我发现这个数组的最大值。像这样的东西:

代码语言:javascript
运行
复制
 double m1=myArray[?,?,0].Max();

我如何使用Linq或其他方法计算它?

EN

回答 3

Stack Overflow用户

发布于 2013-06-11 18:37:21

如果你想得到数组的某个子集的最大值,你可以这样做:

代码语言:javascript
运行
复制
double m1 = 
    (from x in Enumerable.Range(0, myArray.GetLength(0))
     from y in Enumerable.Range(0, myArray.GetLength(1))
     select myArray[x, y, 0])
    .Max();

如果你想得到数组中所有元素的最大值,你可以这样做

代码语言:javascript
运行
复制
double m1 = myArray.Cast<double>().Max();

但是,您可以通过实现自己的扩展方法获得显著的性能提升,如下所示:

代码语言:javascript
运行
复制
public static IEnumerable<T> Flatten<T>(this T[,,] arry) {
    foreach(T x in arry) yield return item;
}

myArray.Flatten().Max();
票数 2
EN

Stack Overflow用户

发布于 2013-06-11 22:37:23

编辑2个

注意,这个扩展同样适用于丑陋但有效的非零基数组的情况,

代码语言:javascript
运行
复制
var nonZeroBasedArray = Array.CreateInstance(
    typeof(double),
    new[] { 4, 4, 3 },
    new[] { -2, -2, 0 });

请注意,前两个维度的范围从-21 (包含yikes)。这段测试代码说明Flatten扩展仍然有效。

代码语言:javascript
运行
复制
var count = 0;
foreach (var element in nonZeroBasedArray.Flatten<double>(null, null, 0))
{
    Console.Write(string.Join(", ", element.Key));
    Console.WriteLine(": {0}", element.Value);
}

Console.WriteLine("Count: {0}", count);
Console.ReadKey();

编辑

因此,使用下面定义的扩展,您可以

代码语言:javascript
运行
复制
var myArray = new double[10000,10000,3];
var ordered = myArray.Flatten<double>(null, null, 0).OrderBy(p => p.Value);
var maxZ0 = ordered.First();
var minZ0 = ordered.Last();

元素类型是一个KeyValuePair<IEnumerable<int>, T>,因此Key允许您向后引用原始数组。

好的,这是一个通用的扩展,最初的灵感来自于p.s.w.g's answer

如果您从Eric Lippert's inspirational CartesianProduct extension开始,

代码语言:javascript
运行
复制
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(
        this IEnumerable<IEnumerable<T>> sequences)
{
    IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
    return sequences.Aggregate(
        emptyProduct,
        (accumulator, sequence) =>
            from accseq in accumulator
            from item in sequence
            select accseq.Concat(new[]
                {
                    item
                }));
}

然后,您可以创建一个函数来生成多维数组的界限集,该函数允许您为某些维数指定固定值。

代码语言:javascript
运行
复制
private static IEnumerable<IEnumerable<int>> GetBoundSequences(
        Array array,
        int?[] definedBounds)
{
    for (var rank = 0; rank < array.Rank; rank++)
    {
        var defined = definedBounds.ElementAtorDefault(rank);

        if (defined.HasValue)
        {
            yield return new[] { defined.Value };
        }
        else
        {
            var min = array.GetLowerBound(rank);
            yield return Enumerable.Range(
                min, 
                (array.GetUpperBound(rank) - min) + 1);
        }
    }
}

您可以使用这两种方法来创建灵活的Flatten<T>扩展,该扩展适用于任何秩的数组。

代码语言:javascript
运行
复制
public static IEnumerable<KeyValuePair<IEnumerable<int>, T>> Flatten<T>(
        this Array array,
        params int?[] definedBounds)
{
    var coordSets = GetBoundSequences(array, definedBounds).CartesianProduct();
    foreach (var coordSet in coordSets)
    {
        var coords = coordSet.ToArray();
        var value = (T)array.GetValue(coords);
        yield return new KeyValuePair<IEnumerable<int>, T>(
            coords,
            value);
    }
}

一旦你有了它,你就可以做一些事情,比如

代码语言:javascript
运行
复制
var myArray = new double[10000,10000,3];
var maxZ0 = myArray.Flatten<double>(null, null, 0).Max(p => p.Value);

这很好,因为它懒惰地只迭代和转换指定的元素。

票数 2
EN

Stack Overflow用户

发布于 2013-06-11 18:35:23

尝尝这个

代码语言:javascript
运行
复制
double[,,] myArray = new double[10000, 10000, 3];

double max = myArray.Cast<double>().Max();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17041922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档