Swift - 将数组转换为字典

时间:2018-06-12 17:04:24

标签: arrays swift dictionary

我只想将一个玩家名称数组转换为字典记分牌,让每个人的初始分数为0.

含义...

var playerNames = ["Harry", "Ron", "Hermione"]

变为 ...

var scoreBoard: [String:Int] = [ "Ron":0, "Harry":0, "Hermione":0 ]

这是我第一次提出一个问题,但我完全被困在感觉如此简单的事情上,以及我发现的所有操作方法/问题都以某种方式解决了。我尝试过以各种方式使用reduce,但最终总是很短。提前谢谢!

8 个答案:

答案 0 :(得分:9)

这是我喜欢使用的快速衬垫:

let scoreboard = playerNames.reduce(into: [String: Int]()) { $0[$1] = 0 }

答案 1 :(得分:4)

reduce绝对是正确使用的内置函数之一,但它就是你想要的。

let names = ["Harry", "Ron", "Hermione"]
let scoreboard: [String: Int] = names.reduce(into: [:], { result, next in
    result[next] = 0
})

它需要2个参数:初始值(在我们的例子中,是一个空字典[:]),以及一个用数组中的每个元素更新结果的闭包。此闭包有2个参数resultnext。我们希望根据result元素更新next。我们的闭包是通过将result[next]设置为0来实现的。

答案 2 :(得分:2)

您可以怀疑reduce(into:)。您只需要将初始值声明为[String:Int]()为所需类型的空Dictionary,然后只需将playerNames中所有键的值设置为0。

var playerNames = ["Harry", "Ron", "Hermione"]
var scoreBoard = playerNames.reduce(into: [String:Int](), { currentScores,player in
    currentScores[player] = 0
})

答案 3 :(得分:2)

如果知道玩家名称完全不同,那么你可以

let playerNames = ["Harry", "Ron", "Hermione", "Ron"]

var scoreBoard = Dictionary(uniqueKeysWithValues: zip(playerNames, AnyIterator { 0 }))

print(scoreBoard) // ["Harry": 0, "Ron": 0, "Hermione": 0]

此处zip用于创建一系列玩家/分数对,从中创建字典。

答案 4 :(得分:1)

使用 reduce(into:_:)

var playerNames = ["Harry", "Ron", "Hermione"]

let playerScore = playerNames.reduce(into: [:]) { counts, playerNames in
    counts[playerNames, default: 0] += 0 
}

print(playerScore)

保持球员姓名的数量(例如重复的名字):

counts[myArray, default: 0] += 1

例如,如果罗恩在游戏开始之前有两个条目(得分> 0),那么你就会知道。

不使用reduce(into:_:)方法并作为扩展程序:

var playerNames = ["Harry", "Ron", "Hermione"]

extension Sequence where Self.Iterator.Element: Hashable {

func freq() -> [Self.Iterator.Element: Int] {
    return reduce([:]) {
            ( iter: [Self.Iterator.Element: Int], element) in
            var dict = iter
            dict[element] = 0
            return dict
        }
    }
}

print(playerNames.freq())
// ["Harry": 0, "Hermione": 0, "Ron": 0]

保持计数(例如,重复的名称):

dict[element, default: -1 ] += 1

答案 5 :(得分:0)

以下是如何做到这一点:

var playerNames = ["Harry", "Ron", "Hermione"]

var dictionary = [String: Int]()
for player in playerNames {
    dictionary[player] = 0
}

答案 6 :(得分:0)

这是另一种方法:

// Implementation 

extension Dictionary {
    static func from(_ array: [Value], key: KeyPath<Value, Key>) -> Dictionary<Key, Value> {
        var dict: Dictionary<Key, Value> = [:]
        array.forEach { dict[$0[keyPath: key]] = $0}
        return dict
    }
}


/// Usage

let array: [String] = ["Banana", "Apple"]

Dictionary.from(array, key: \.self)

// or if you have a more complex object

struct Foo {
    let id: Int
}


let array2: [Foo] = [Foo(id: 1), Foo(id: 2)]

Dictionary.from(array2, key: \.id)

答案 7 :(得分:-1)

基于jmad8答案

详细信息

  • Swift 5.3
  • Xcode 12.0.1(12A7300)

解决方案

extension Sequence {
    func toDictionary<Key: Hashable, Value>(where closure: (Element) -> (Key, Value)) -> [Key: Value] {
        reduce(into: [Key: Value]()) { (result, element) in
            let components = closure(element)
            result[components.0] = components.1
        }
    }
    
    func toCompactDictionary<Key: Hashable, Value>(where closure: (Element) -> ((Key, Value)?)) -> [Key: Value] {
        reduce(into: [Key: Value]()) { (result, element) in
            guard let components = closure(element) else { return }
            result[components.0] = components.1
        }
    }
}

用法

// Sample 1

print(languages.toDictionary { (string) -> (Character, String) in
    return (string.first!, string)
})

print(languages.toCompactDictionary { (string) -> (Character, String)? in
    guard let character = string.first, character != Character("J") else { return nil }
    return (character, string)
})


// Sample 2

print(languages.enumerated().toDictionary { (data) -> (Int, String) in
    return (data.offset, data.element)
})

// Shorter version of sample 2

print(languages.enumerated().toDictionary { ($0.offset, $0.element) })

// Sample 3

struct Order {
    let id: Int
    let desctiption: String
}

let orders = [
                Order(id: 0, desctiption: "Apple"),
                Order(id: 1, desctiption: "Banana"),
                Order(id: 2, desctiption: "watermelon")
            ]

print(orders.toDictionary { ($0.id, $0) })