0
auto getMultidimensionalArrayShape( T )( T array )
{
  static assert( isArray!( T ) );

  // Retrieve the shape of the input array and double check that
  // the arrays from a same dimension have the same length.
  size_t[] shape;
  // ...

  return shape;
}

getMultidimensionalArrayShape( [1, 2, 3] )  //< returns [3]
getMultidimensionalArrayShape( [[1, 2, 3], [4, 5, 6]] )  //< returns [3][2]
// and so on...

単純に、深さ優先の方法で反復して、インデックス0で各配列のサイズを取得します。次に、同じ次元の他の配列の長さが、インデックス0で見つけたものと長さが一致するかどうかを確認します。すべてが一貫していることを確認するために、しかし私はもっと良い方法があるに違いないと思っています...誰かがアイデアを持っていますか?

4

2 に答える 2

2

これには、再帰的なソリューションが必要です。

template depthOf(T){
    static if(isIterable!T)
        enum depthOf=1+depthOf!(ForeachType!T);
    else
        enum depthOf=0;
}

immutable(long)[] getMultidimensionalArrayShape(bool verify=true,T)(T array){
    static assert(isArray!T);
    static if(!isArray!(ForeachType!T)){
        return [array.length];
    }else{
        if(0==array.length)
            return [0L].replicate(depthOf!T).idup;
        const elementDimension=array[0].getMultidimensionalArrayShape();
        static if(verify){
            foreach(child;array[1..$]){
                if(child.getMultidimensionalArrayShape()!=elementDimension)
                    throw new Exception("Shape is not uniform");
            }
        }
        return (array.length~elementDimension).idup;
    }
}

実際には、関数がそれ自体を呼び出すことはないため、実際には再帰ではありません(関数は同じテンプレートから作成された他の関数を呼び出します)。静的再帰はより良い名前です。

于 2012-09-21T19:27:08.227 に答える
0

これが私が書いたものです。基本的に、同じ深度レベルのすべての配列を収集し、それらがすべて等しいことを確認した後、それらの次元サイズを取得しています。うまく機能しているように聞こえますが、唯一のことは、depthLevelArraysの長さが0に等しい場合にどうすればよいかわからないということです。それも意味がありますか、それとも例外をスローする必要がありますか?

import std.stdio;
import std.traits;


void internal( T )( T[] depthLevelArrays, ref size_t[] shape )
{
  if ( depthLevelArrays.length == 0 )
      writeln( "what to do here?" );

  static if ( isArray!( ForeachType!( T ) ) )
  {
    ForeachType!( T )[] children;
    size_t dimensionSize = depthLevelArrays[0].length;
    foreach ( element; depthLevelArrays )
    {
      if ( element.length != dimensionSize )
        throw new Exception( "Shape is not uniform" );

      foreach ( child; element )
        children ~= child;
    }

    internal( children, shape );
  }
  else
  {
    size_t dimensionSize = depthLevelArrays[0].length;
    foreach ( element; depthLevelArrays )
      if ( element.length != dimensionSize )
        throw new Exception( "Shape is not uniform" );
  }

  shape ~= dimensionSize;
}


auto getMultidimensionalArrayShape( T )( T array )
{
  static assert( isArray!( T ) );
  size_t[] shape;
  internal( [array], shape );
  return shape;
}


void main()
{
  immutable auto array1d = [1.0, 2.5, 3.4];
  auto shape1 = getMultidimensionalArrayShape( array1d );
  writeln( "shape1: ", shape1 ); //< [3]

  int[5][2] array2d = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]];
  auto shape2 = getMultidimensionalArrayShape( array2d );
  writeln( "shape2: ", shape2 );  //< [5][2]

  auto shape3 = getMultidimensionalArrayShape(
      [[[1, 2], [3, 4], [5, 6], [7, 8]],
      [[9, 10], [11, 12], [13, 14], [15, 16]],
      [[17, 18], [19, 20], [21, 22], [23, 24]]] );
  writeln( "shape3: ", shape3 ); //< [2][4][3]

  const int[5][4][3][2] array4d;
  auto shape4 = getMultidimensionalArrayShape( array4d );
  writeln( "shape4: ", shape4 ); //< [5][4][3][2]
}
于 2012-09-22T10:25:40.390 に答える