有没有一种简单的方法可以遍历多维数组并在Swift中转换每个元素?

时间:2020-10-24 01:08:23

标签: ios swift

如果我有一个多维的经度和纬度数组,例如:

let inputLatLongArray = [[[
  ["-100.7777777775", "99.2222222"],
  ["-100.777777777", "87.2222222"],
  ["-100.777777777",  "34.2222222"],
  ["-100.777777777", "99.2222222"],
  ["-100.777777777", "99.2222222"]
 ]]]

如何遍历和转换元素,以便每个嵌套纬度/经度仅具有2个小数位?

预期输出:

let expectedLatLongArray = [[[
  ["-100.77", "99.22"],      
  ["-100.77", "87.22"], 
  ["-100.77", "34.22"], 
  ["-100.77", "99.22"], 
  ["-100.77", "99.22"]
 ]]]

代码:

这是我到目前为止的内容。我的想法是使用flatMap,然后向下映射到嵌套数组中,但这似乎也不正确。有没有简单的方法可以做到这一点?

func roundLatAndLong(with latLongArray: [[[[String, String]]]]) -> [[[[String, String]]]] {
    let coordinates = latLongArray.flatMap { $0 }.map({ $0 }).map({ //Rounded both array positions down to 2 decimal places })
   return coordinates
}

func rounded(toDecimalPlaces n: Int) -> String {
  return String(format: "%.\(n)f", self)
}

3 个答案:

答案 0 :(得分:2)

如果您的数据类型为Double,则没有小数位数。如果您尝试将值四舍五入到给定的小数位数,则会得到接近但不完全接近该值的值。这是因为二进制浮点不能完全表示大多数十进制值。如果您确实想将值转换为精确到小数位数的值,则应使用Decimal类型。

您可以很容易地将lat / long Double值数组转换为具有给定小数位数的字符串。

如果您有一个包含纬度/经度的结构体数组或一个元组的数组,那将会更加整洁。甚至是键为“ lat”和“ long”的字典的组合

答案 1 :(得分:2)

您可以执行以下操作:

func nestedTransform<InElement, OutElement>(nested: [[[[InElement]]]], transform: (InElement) -> OutElement) -> [[[[OutElement]]]]
{
    return nested.map {$0.map { $0.map { $0.map(transform) }}}
}

我认为,在您的尝试中,您只是做了一点嵌套,即您是在链接而不是嵌套map调用。

您将这样使用:

let roundedResult = nestedTransform(nested: inputLatLongArray) { $0.rounded(toDecimalPlaces: 8) }

假设在InElement上存在适当的扩展名。您已编辑问题以删除原始的Double数组。因此,此答案用于解决嵌套数组的映射。转换的实现完全取决于您!

我也强烈建议您阅读@DuncanC的答案和@LeoDaubus的有关为什么原始转换不明智的评论。

答案 2 :(得分:2)

您可以逐步扩展Array以允许在多维转换上进行转换:

extension Array {
    func map2<T, U>(_ transform: (T) -> U) -> [[U]] where Element == [T] {
        map { $0.map(transform) }
    }
    
    func map3<T,U>(_ transform: (T) -> U) -> [[[U]]] where Element == [[T]] {
        map { $0.map2(transform) }
    }
    
    func map4<T,U>(_ transform: (T) -> U) -> [[[[U]]]] where Element == [[[T]]] {
        map { $0.map3(transform) }
    }
}

然后您可以使用以下扩展名:

let inputLatLongArray = [[[
    ["-98.73264361706984", "38.5447223260328"],
    ["-98.73255257987707", "38.543630550793544"],
    ["-98.7302159585956",  "38.54506646913993"],
    ["-98.73200635672036", "38.54556488037536"],
    ["-98.73264361706984", "38.5447223260328"]
]]]
let transform: (String) -> String = {
    return String(format: "%.\(8)f", Double($0) ?? 0.0)
}
let transformedArray = inputLatLongArray.map4(transform)
print(transformedArray)