【问题标题】:How to generate a 2D-array from a 1D-array using map and filter?如何使用映射和过滤器从一维数组生成二维数组?
【发布时间】:2018-10-08 13:16:14
【问题描述】:

我今天使用循环获得了所需的输出,但是如何使用 map 和 filter 将这个循环与单行表达式交换?

我从一系列国家/地区开始。从这个我使用 map 生成第二个带有首字母的数组。我现在想使用 map 和 filter 构建一个二维数组,其中包含具有相同首字母的所有国家/地区,这样我就可以摆脱我今天使用的循环。

let countries = ["Albania", "Algeria", "Angola", "Bahamas", "Bahrain", "Canada"]

var initials = Set(countries.map { $0.prefix(1) }).sorted()

func countriesByInitial() -> [[String]] {
    var result = [[String]]()
    for initial in initials {
        result.append(countries.filter { $0.prefix(1) == initial })
    }
    return result
}

【问题讨论】:

  • 发布您的代码,而不是屏幕截图...
  • 复制/粘贴代码,而不是截图。
  • 这是一个真实世界的示例,说明为什么您应该真正发布代码而不是图像:除了我需要复制/粘贴您的代码之外,由于某种原因,我连接到一个可以访问的网络到 i.stack.imgur.com 图像被阻止!因此我什至无法查看代码。
  • 好的,我现在已经发布了代码。
  • 你的数组总是排序的吗?

标签: ios arrays swift multidimensional-array higher-order-functions


【解决方案1】:

你可以通过group > sort > map组合来实现:

let countries = ["Algeria", "Albania", "Belarus", "Bahamas", "Canada"]
let groupedDict = Dictionary(grouping: countries, by: { $0.prefix(1) })
let sortedDict = groupedDict.sorted(by: { $0.key < $1.key })
let arr2D = sortedDict.map({ $0.value })

你可以写成一行:

let arr = (Dictionary(grouping: countries, by: { $0.prefix(1) })).sorted(by: { $0.key < $1.key }).map({ $0.value })

您也可以在数组上使用 reduce:

// $0 的类型为[[String]]

// $1 的类型为String

let arr2D: [[String]] = countries.reduce(into: []) {
    let checkChar = $1.first
    if let idx = $0.index(where: {$0.first?.first == checkChar }) {
        $0[idx].append($1)
    } else {
        $0.append([$1])
    }
}

【讨论】:

  • arr2D 是一个数组。你需要的输出是什么?
  • @DiezNobach 正确阅读了答案。它提供了您想要的二维数组。很好的答案顺便说一句 Ankit。 拍手 拍手
  • 感谢@MartinR 指出,我忘了更改我在操场上尝试的变量名。现在更新答案。
  • 好的,我换个说法。我正在寻找一种直接在数组上执行此操作而无需进行字典转换的方法。
【解决方案2】:

如果你的数组已经排序,你可以使用 Swift 4 方法reduce(into:),否则你只需要在分组之前对其进行排序:

let countries = ["Albania", "Algeria", "Angola", "Bahamas", "Bahrain", "Canada"]

let grouped: [[String]] = countries.reduce(into: []) {
    if $0.last?.last?.prefix(1) == $1.prefix(1) {
        $0[$0.index(before: $0.endIndex)].append($1)
    } else {
        $0.append([$1])
    }
}

print(grouped)   // [["Albania", "Algeria", "Angola"], ["Bahamas", "Bahrain"], ["Canada"]]\n"

【讨论】:

  • countries.reduce(into: [["0"]]){(result: inout [[String]], string: String) in _ = result.last!.last!.first! != 字符串。第一! ? result.append([string]) : result[result.endIndex - 1].append(string) }.dropFirst()
【解决方案3】:

您可以映射 过滤 countries 字符串的第一个字母设置的initial

let countries = ["Albania", "Algeria", "Angola", "Bahamas", "Bahrain", "Canada"]
var initials = Set(countries.map { $0.prefix(1) }).sorted()

let array = initials.map { letter -> [String] in
    return countries.filter { $0.prefix(1) == letter }
}

因此,array 是一个字符串数组 ([[String]]),如:

[[“阿尔巴尼亚”、“阿尔及利亚”、“安哥拉”]、[“巴哈马”、“巴林”]、[“加拿大”]]

【讨论】:

  • 这将为每个首字母执行一个过滤器
  • 这不是问题的有效解决方案,太多不必要的循环。
猜你喜欢
  • 2011-01-10
  • 2014-09-03
  • 2016-11-22
  • 2018-12-28
  • 1970-01-01
  • 2020-06-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多