Swift:如何交换四维阵列的两个轴?

时间:2016-12-15 02:22:51

标签: arrays swift swap

要正确地将数据提供给函数,我需要在Swift中交换四维数组中的两个轴。我想知道如何实现或为此目的有任何有用的功能。

在Python中,如果我使用numpy.swapaxes(a, axis1, axis2),那就很简单(https://docs.scipy.org/doc/numpy/reference/generated/numpy.swapaxes.html):

def swapaxes_from_tail_to_head(nparray):
    nparray = np.swapaxes(nparray, 2, 3)
    nparray = np.swapaxes(nparray, 1, 2)
    nparray = np.swapaxes(nparray, 0, 1)
    return nparray

请注意,如果数组是二维的,我可以这样做:

func prettyPrintMatrix( _ matrix:[[Int]] ) {
  for array in matrix {
    print( array )
  }
}

func main() -> (){
  print( "MatrixTranspose_Demo" )
  print()

  let matrix = 
  [
    [ 1, 2, 3 ],
    [ 4, 5, 6 ],
  ]

  print( "Matrix:")
  prettyPrintMatrix( matrix )
  print()

  let transpose = transposeMatrix( matrix )

  print( "Transpose matrix:")
  prettyPrintMatrix( transpose )
  print()
}

func transposeMatrix( _ matrix:[[Int]] ) -> [[Int]] {    
  var result = [[Int]](
    repeating: [Int]( repeating: 0, count: matrix.count ), 
    count: matrix[ 0 ].count
  )

  for i in 0 ..< matrix.count {
    for k in 0 ..< matrix[ 0 ].count {
        result[ k ][ i ] = matrix[ i ][ k ]
    }
  }
  return result
}

main()
// Reference: http://www.runswiftlang.com/

如果您对如何为四维(或更多)阵列做交换操作有任何想法,请告诉我。感谢您的帮助。

3 个答案:

答案 0 :(得分:0)

最简单的方法是硬编码以下所有内容:

final Map<String, Object> results = new HashMap<>();

while (jsonReader.hasNext()) {
    final String name = jsonReader.nextName();

    switch (jsonReader.peek()) {
        case BOOLEAN:
            results.put(name, jsonReader.nextBoolean());
            break;
        case NAME:
            results.put(name, jsonReader.nextName());
            break;
        case NULL:
            results.put(name, null);
            break;
        case NUMBER:
            // results.put(name, jsonReader.nextInt()); TODO: Find out how to differentiate between int, long and double
            break;
        case STRING:
            results.put(name, jsonReader.nextString());
            break;
        default:
            jsonReader.skipValue();
            break;
    }
}

要减少代码量,可以使用类来更改for循环的顺序。 Change order of for loops?

答案 1 :(得分:0)

为二维矩阵制作转置函数相当容易:

func transpose<T>(_ matrix:[[T]]) -> [[T]]
{
  return matrix.reduce([[T]]())
         {
           zip($0,$1).map{$0+[$1]} 
           + $0.dropFirst($1.count) 
           + $1.dropFirst($0.count).map{[$0]} 
         }
}

一旦你有了这个,任何维度的所有其他转置都可以转换为连续维度上的一系列2d转置(基本上交换它们)

let array12   = (1...4).map{ n in (1...4).map{n*10 + $0} }
let array123  = (1...4).map{ n in array12.map{ $0.map{ n*100 + $0 } } }
let array1234 = (1...4).map{ n in array123.map{ $0.map{ $0.map{ n*1000 + $0 } } } }

let array2134 = transpose(array1234)           // swap dimensions 1 and 2
let array1324 = array1234.map{transpose($0)}   // swap dimensions 2 and 3
let array1243 = array1234.map{$0.map{transpose($0)}} // swap dimensions 3 and 4

重复使用这3个基本维度交换,可以实现4个维度的所有其他组合。

let array2143 = array2134.map{$0.map{transpose($0)}}
let array2413 = array2143.map{transpose($0)}
let array4213 = transpose(array2413)
let array4231 = array4213.map{$0.map{transpose($0)}}
let array4321 = array4231.map{transpose($0)}
// and so on ...

为了帮助测试这个,我为我在操场上使用的矩阵做了一个4d打印功能:

它以行列顺序打印,因此您将尺寸1作为&#34;块&#34;的垂直组,尺寸2作为块的列,尺寸3是每个块的行,尺寸4是列的列每个街区:

func print4d<T>(_ matrix4d:[[[[T]]]])
{
   var lines:[String] = []
   for d1 in matrix4d
   {
      lines = []
      for (indent,d2) in d1.enumerated()
      {
         let indentWidth = indent * 80
         var lineNumber = 0
         let blankLine = "".padding(toLength:indentWidth, withPad:" ", startingAt:0)
         for d34 in d2
         {
            while lines.count <= lineNumber
            { lines.append(blankLine) }
            lines[lineNumber] = lines[lineNumber]
                                .padding(toLength:indentWidth, withPad:" ", startingAt:0)
                              + "  \(d34)" 

            lineNumber += 1
         }
         for index in lines.indices
         {
            while lines[index].contains("  ")
            { lines[index] = lines[index].replacingOccurrences(of: "  ", with: " ") }
         }             
      }
      lines.forEach{ print($0) }
      print("")
   }
}



 4d matrix :  d1, d2, d3, d4
 ===========================
 [1111, 1112, 1113, 1114] [1211, 1212, 1213, 1214] [1311, 1312, 1313, 1314] [1411, 1412, 1413, 1414]
 [1121, 1122, 1123, 1124] [1221, 1222, 1223, 1224] [1321, 1322, 1323, 1324] [1421, 1422, 1423, 1424]
 [1131, 1132, 1133, 1134] [1231, 1232, 1233, 1234] [1331, 1332, 1333, 1334] [1431, 1432, 1433, 1434]
 [1141, 1142, 1143, 1144] [1241, 1242, 1243, 1244] [1341, 1342, 1343, 1344] [1441, 1442, 1443, 1444]

 [2111, 2112, 2113, 2114] [2211, 2212, 2213, 2214] [2311, 2312, 2313, 2314] [2411, 2412, 2413, 2414]
 [2121, 2122, 2123, 2124] [2221, 2222, 2223, 2224] [2321, 2322, 2323, 2324] [2421, 2422, 2423, 2424]
 [2131, 2132, 2133, 2134] [2231, 2232, 2233, 2234] [2331, 2332, 2333, 2334] [2431, 2432, 2433, 2434]
 [2141, 2142, 2143, 2144] [2241, 2242, 2243, 2244] [2341, 2342, 2343, 2344] [2441, 2442, 2443, 2444]

 [3111, 3112, 3113, 3114] [3211, 3212, 3213, 3214] [3311, 3312, 3313, 3314] [3411, 3412, 3413, 3414]
 [3121, 3122, 3123, 3124] [3221, 3222, 3223, 3224] [3321, 3322, 3323, 3324] [3421, 3422, 3423, 3424]
 [3131, 3132, 3133, 3134] [3231, 3232, 3233, 3234] [3331, 3332, 3333, 3334] [3431, 3432, 3433, 3434]
 [3141, 3142, 3143, 3144] [3241, 3242, 3243, 3244] [3341, 3342, 3343, 3344] [3441, 3442, 3443, 3444]

 [4111, 4112, 4113, 4114] [4211, 4212, 4213, 4214] [4311, 4312, 4313, 4314] [4411, 4412, 4413, 4414]
 [4121, 4122, 4123, 4124] [4221, 4222, 4223, 4224] [4321, 4322, 4323, 4324] [4421, 4422, 4423, 4424]
 [4131, 4132, 4133, 4134] [4231, 4232, 4233, 4234] [4331, 4332, 4333, 4334] [4431, 4432, 4433, 4434]
 [4141, 4142, 4143, 4144] [4241, 4242, 4243, 4244] [4341, 4342, 4343, 4344] [4441, 4442, 4443, 4444]



 4d matrix :  d2, d1, d3, d4
 ===========================
 [1111, 1112, 1113, 1114] [2111, 2112, 2113, 2114] [3111, 3112, 3113, 3114] [4111, 4112, 4113, 4114]
 [1121, 1122, 1123, 1124] [2121, 2122, 2123, 2124] [3121, 3122, 3123, 3124] [4121, 4122, 4123, 4124]
 [1131, 1132, 1133, 1134] [2131, 2132, 2133, 2134] [3131, 3132, 3133, 3134] [4131, 4132, 4133, 4134]
 [1141, 1142, 1143, 1144] [2141, 2142, 2143, 2144] [3141, 3142, 3143, 3144] [4141, 4142, 4143, 4144]

 [1211, 1212, 1213, 1214] [2211, 2212, 2213, 2214] [3211, 3212, 3213, 3214] [4211, 4212, 4213, 4214]
 [1221, 1222, 1223, 1224] [2221, 2222, 2223, 2224] [3221, 3222, 3223, 3224] [4221, 4222, 4223, 4224]
 [1231, 1232, 1233, 1234] [2231, 2232, 2233, 2234] [3231, 3232, 3233, 3234] [4231, 4232, 4233, 4234]
 [1241, 1242, 1243, 1244] [2241, 2242, 2243, 2244] [3241, 3242, 3243, 3244] [4241, 4242, 4243, 4244]

 [1311, 1312, 1313, 1314] [2311, 2312, 2313, 2314] [3311, 3312, 3313, 3314] [4311, 4312, 4313, 4314]
 [1321, 1322, 1323, 1324] [2321, 2322, 2323, 2324] [3321, 3322, 3323, 3324] [4321, 4322, 4323, 4324]
 [1331, 1332, 1333, 1334] [2331, 2332, 2333, 2334] [3331, 3332, 3333, 3334] [4331, 4332, 4333, 4334]
 [1341, 1342, 1343, 1344] [2341, 2342, 2343, 2344] [3341, 3342, 3343, 3344] [4341, 4342, 4343, 4344]

 [1411, 1412, 1413, 1414] [2411, 2412, 2413, 2414] [3411, 3412, 3413, 3414] [4411, 4412, 4413, 4414]
 [1421, 1422, 1423, 1424] [2421, 2422, 2423, 2424] [3421, 3422, 3423, 3424] [4421, 4422, 4423, 4424]
 [1431, 1432, 1433, 1434] [2431, 2432, 2433, 2434] [3431, 3432, 3433, 3434] [4431, 4432, 4433, 4434]
 [1441, 1442, 1443, 1444] [2441, 2442, 2443, 2444] [3441, 3442, 3443, 3444] [4441, 4442, 4443, 4444]



 4d matrix :  d1, d2, d4, d3
 ===========================
 [1111, 1121, 1131, 1141] [2111, 2121, 2131, 2141] [3111, 3121, 3131, 3141] [4111, 4121, 4131, 4141]
 [1112, 1122, 1132, 1142] [2112, 2122, 2132, 2142] [3112, 3122, 3132, 3142] [4112, 4122, 4132, 4142]
 [1113, 1123, 1133, 1143] [2113, 2123, 2133, 2143] [3113, 3123, 3133, 3143] [4113, 4123, 4133, 4143]
 [1114, 1124, 1134, 1144] [2114, 2124, 2134, 2144] [3114, 3124, 3134, 3144] [4114, 4124, 4134, 4144]

 [1211, 1221, 1231, 1241] [2211, 2221, 2231, 2241] [3211, 3221, 3231, 3241] [4211, 4221, 4231, 4241]
 [1212, 1222, 1232, 1242] [2212, 2222, 2232, 2242] [3212, 3222, 3232, 3242] [4212, 4222, 4232, 4242]
 [1213, 1223, 1233, 1243] [2213, 2223, 2233, 2243] [3213, 3223, 3233, 3243] [4213, 4223, 4233, 4243]
 [1214, 1224, 1234, 1244] [2214, 2224, 2234, 2244] [3214, 3224, 3234, 3244] [4214, 4224, 4234, 4244]

 [1311, 1321, 1331, 1341] [2311, 2321, 2331, 2341] [3311, 3321, 3331, 3341] [4311, 4321, 4331, 4341]
 [1312, 1322, 1332, 1342] [2312, 2322, 2332, 2342] [3312, 3322, 3332, 3342] [4312, 4322, 4332, 4342]
 [1313, 1323, 1333, 1343] [2313, 2323, 2333, 2343] [3313, 3323, 3333, 3343] [4313, 4323, 4333, 4343]
 [1314, 1324, 1334, 1344] [2314, 2324, 2334, 2344] [3314, 3324, 3334, 3344] [4314, 4324, 4334, 4344]

 [1411, 1421, 1431, 1441] [2411, 2421, 2431, 2441] [3411, 3421, 3431, 3441] [4411, 4421, 4431, 4441]
 [1412, 1422, 1432, 1442] [2412, 2422, 2432, 2442] [3412, 3422, 3432, 3442] [4412, 4422, 4432, 4442]
 [1413, 1423, 1433, 1443] [2413, 2423, 2433, 2443] [3413, 3423, 3433, 3443] [4413, 4423, 4433, 4443]
 [1414, 1424, 1434, 1444] [2414, 2424, 2434, 2444] [3414, 3424, 3434, 3444] [4414, 4424, 4434, 4444]



 4d matrix :  d1, d3, d2, d4
 ===========================
 [1111, 1112, 1113, 1114] [1121, 1122, 1123, 1124] [1131, 1132, 1133, 1134] [1141, 1142, 1143, 1144]
 [2111, 2112, 2113, 2114] [2121, 2122, 2123, 2124] [2131, 2132, 2133, 2134] [2141, 2142, 2143, 2144]
 [3111, 3112, 3113, 3114] [3121, 3122, 3123, 3124] [3131, 3132, 3133, 3134] [3141, 3142, 3143, 3144]
 [4111, 4112, 4113, 4114] [4121, 4122, 4123, 4124] [4131, 4132, 4133, 4134] [4141, 4142, 4143, 4144]

 [1211, 1212, 1213, 1214] [1221, 1222, 1223, 1224] [1231, 1232, 1233, 1234] [1241, 1242, 1243, 1244]
 [2211, 2212, 2213, 2214] [2221, 2222, 2223, 2224] [2231, 2232, 2233, 2234] [2241, 2242, 2243, 2244]
 [3211, 3212, 3213, 3214] [3221, 3222, 3223, 3224] [3231, 3232, 3233, 3234] [3241, 3242, 3243, 3244]
 [4211, 4212, 4213, 4214] [4221, 4222, 4223, 4224] [4231, 4232, 4233, 4234] [4241, 4242, 4243, 4244]

 [1311, 1312, 1313, 1314] [1321, 1322, 1323, 1324] [1331, 1332, 1333, 1334] [1341, 1342, 1343, 1344]
 [2311, 2312, 2313, 2314] [2321, 2322, 2323, 2324] [2331, 2332, 2333, 2334] [2341, 2342, 2343, 2344]
 [3311, 3312, 3313, 3314] [3321, 3322, 3323, 3324] [3331, 3332, 3333, 3334] [3341, 3342, 3343, 3344]
 [4311, 4312, 4313, 4314] [4321, 4322, 4323, 4324] [4331, 4332, 4333, 4334] [4341, 4342, 4343, 4344]

 [1411, 1412, 1413, 1414] [1421, 1422, 1423, 1424] [1431, 1432, 1433, 1434] [1441, 1442, 1443, 1444]
 [2411, 2412, 2413, 2414] [2421, 2422, 2423, 2424] [2431, 2432, 2433, 2434] [2441, 2442, 2443, 2444]
 [3411, 3412, 3413, 3414] [3421, 3422, 3423, 3424] [3431, 3432, 3433, 3434] [3441, 3442, 3443, 3444]
 [4411, 4412, 4413, 4414] [4421, 4422, 4423, 4424] [4431, 4432, 4433, 4434] [4441, 4442, 4443, 4444]



 4d matrix :  d4, d2, d3, d1
 ===========================
 [1111, 2111, 3111, 4111] [1211, 2211, 3211, 4211] [1311, 2311, 3311, 4311] [1411, 2411, 3411, 4411]
 [1121, 2121, 3121, 4121] [1221, 2221, 3221, 4221] [1321, 2321, 3321, 4321] [1421, 2421, 3421, 4421]
 [1131, 2131, 3131, 4131] [1231, 2231, 3231, 4231] [1331, 2331, 3331, 4331] [1431, 2431, 3431, 4431]
 [1141, 2141, 3141, 4141] [1241, 2241, 3241, 4241] [1341, 2341, 3341, 4341] [1441, 2441, 3441, 4441]

 [1112, 2112, 3112, 4112] [1212, 2212, 3212, 4212] [1312, 2312, 3312, 4312] [1412, 2412, 3412, 4412]
 [1122, 2122, 3122, 4122] [1222, 2222, 3222, 4222] [1322, 2322, 3322, 4322] [1422, 2422, 3422, 4422]
 [1132, 2132, 3132, 4132] [1232, 2232, 3232, 4232] [1332, 2332, 3332, 4332] [1432, 2432, 3432, 4432]
 [1142, 2142, 3142, 4142] [1242, 2242, 3242, 4242] [1342, 2342, 3342, 4342] [1442, 2442, 3442, 4442]

 [1113, 2113, 3113, 4113] [1213, 2213, 3213, 4213] [1313, 2313, 3313, 4313] [1413, 2413, 3413, 4413]
 [1123, 2123, 3123, 4123] [1223, 2223, 3223, 4223] [1323, 2323, 3323, 4323] [1423, 2423, 3423, 4423]
 [1133, 2133, 3133, 4133] [1233, 2233, 3233, 4233] [1333, 2333, 3333, 4333] [1433, 2433, 3433, 4433]
 [1143, 2143, 3143, 4143] [1243, 2243, 3243, 4243] [1343, 2343, 3343, 4343] [1443, 2443, 3443, 4443]

 [1114, 2114, 3114, 4114] [1214, 2214, 3214, 4214] [1314, 2314, 3314, 4314] [1414, 2414, 3414, 4414]
 [1124, 2124, 3124, 4124] [1224, 2224, 3224, 4224] [1324, 2324, 3324, 4324] [1424, 2424, 3424, 4424]
 [1134, 2134, 3134, 4134] [1234, 2234, 3234, 4234] [1334, 2334, 3334, 4334] [1434, 2434, 3434, 4434]
 [1144, 2144, 3144, 4144] [1244, 2244, 3244, 4244] [1344, 2344, 3344, 4344] [1444, 2444, 3444, 4444]

答案 2 :(得分:0)

Swift中缺乏对矩阵操作的直接支持让我烦恼所以我玩了数组扩展并使用了一些方法可能会让事情变得更容易。

extension Array
{
   func asMatrix(_ axisSizes: Int ...) -> [Any] { return asMatrix(axisSizes) }
   func asMatrix(_ axisSizes:[Int])    -> [Any]
   {
      if count == 0 { return [] }

      let requiredVectorSize = axisSizes.reduce(1,*)
      let flatData           = asVector
      var newArray:[Any]     = flatData 
      while newArray.count < requiredVectorSize { newArray = newArray + flatData }

      for axisSize in axisSizes.dropFirst().reversed()
      {
         newArray = (0..<newArray.count/axisSize)
                    .map{($0*axisSize,($0+1)*axisSize)}
                    .map{newArray[$0..<$1].map{$0}}
      }
      return newArray   
   }

   var matrixSize:[Int]
   {
      get { return [count] + ((first as? [Any])?.matrixSize ?? []) }
      set { self = asVector.asMatrix(newValue) as! [Element] }
   }

   func vectorIndex(of indexes:[Int]) -> Int
   {
      return zip(matrixSize,indexes).reduce(0){ $0 * $1.0 + $1.1 }      
   }

   func matrixIndex(of vectorIndex:Int) -> [Int]
   {
      var result:[Int] = []
      var vectorIndex  = vectorIndex
      for dim in matrixSize.reversed()
      {
        result.append(vectorIndex % dim)
        vectorIndex = vectorIndex / dim
      } 
      return result.reversed()
   }

   func enumeratedMatrix() -> [([Int],Any)]
   {
      return asVector.enumerated().map{(self.matrixIndex(of:$0),$1)}
   }

   var vectorSize:Int { return matrixSize.reduce(1,*) }

   var asVector:[Any] 
   {
     get { return (self as? [[Any]])?.reduce(Array<Any>()){$0+$1}.asVector ?? self}
     set { self = newValue.asMatrix(matrixSize) as! [Element] }
   }

   subscript(indexes:[Int]) -> Any
   {
      get {  return indexes.reduce(self as Any){ ($0 as! [Any])[$1] } }
      set {  
             if indexes.count == 1 
             { 
               self[indexes.first!] = newValue as! Element
             }
             else 
             {
                var subArray         = self[indexes.first!] as! Array<Any>
                let subIndexes:[Int] = indexes.dropFirst().map{$0}
                subArray[subIndexes] = newValue
                self[indexes.first!] = subArray as! Element
             }
          }
   }

   func transposedMatrix(_ dim1:Int=0, _ dim2:Int=1) -> [Any]
   {
      if dim1 == dim2 { return self }

      var transposedSizes = matrixSize
      swap(&transposedSizes[dim1],&transposedSizes[dim2])

      var indexMap        = (0..<transposedSizes.count).map{$0}
      swap(&indexMap[dim1],&indexMap[dim2])

      let mapping = (0..<vectorSize)
                    .map{($0, matrixIndex(of:$0))}
                    .map{(vi,mi) in (vi,indexMap.map{mi[$0]})}
                    .map{(vi,mi) in (vi,self.vectorIndex(of:mi)) }

      var flatData = asVector

      return mapping
             .sorted{$0.1 < $1.1}
             .map{flatData[$0.0]}
             .asMatrix(transposedSizes)

   }
}

剩下的唯一问题是我必须使用类型擦除,因此这些矩阵被视为数组或任何并且需要某些类型转换才能实际使用。然而,操纵它们更容易:

// initialized from vectors:
//
let squareNumbers = (0..<64).map{$0}
var chessBoard    = squareNumbers.asMatrix(8,8)

// swapping axes
//
let m4Dim4842 = [0].asMatrix(4,8,4,2)           // 1 element vector is repeated to fill content
let m4Dim2844 = m4Dim4842.transposedMatrix(3,0) // swapped dimensions 0 and 3

// double brackets to access elements
//
let queenPos      = chessBoard[[4,0]] as! Int
chessBoard[[4,0]] = queenPos


// enumeration to traverse all elements
// (and data assignment using a 1d vector)
chessBoard.asVector = chessBoard.enumeratedMatrix().map{$0.0[0]==$0.0[1] ? 1 : 0}