我只想将一个玩家名称数组转换为字典记分牌,让每个人的初始分数为0.
含义... 的
var playerNames = ["Harry", "Ron", "Hermione"]
变为 ...
var scoreBoard: [String:Int] = [ "Ron":0, "Harry":0, "Hermione":0 ]
这是我第一次提出一个问题,但我完全被困在感觉如此简单的事情上,以及我发现的所有操作方法/问题都以某种方式解决了。我尝试过以各种方式使用reduce,但最终总是很短。提前谢谢!
答案 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个参数result
和next
。我们希望根据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答案
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) })