将 [[(Int, String)]] 组合成 [(Int, String)] 的优雅方式?
Elegant way to combine [[(Int, String)]] into [(Int, String)]?
我用的是Swift4,Xcode9.
具体来说,我有一个数组 [[(Int, String)]] 数组,其中 Int 是一个等级,String 是一个名称 + 项目...使用 .joined(separator: ";") 组合.
数据可能如下所示:
[[1,"My Name;Item1;Item2"], [(5,"My Name;Item2;Item3"), (3,"My Second Name;Item1")]]
我想合并内部数组,以便:
- Int 添加基于名称的匹配项(最多为“;”)
- 字符串添加后续项目(如果不存在)
结合我上面的例子应该会导致:
[(6,"My Name;Item1;Item2;Item3"), (3,"My Second Name;Item1")]
即输入为 [[(Int, String)]]
,输出为 [(Int, String)]
目前,我可以通过一组相当复杂的循环来实现这一点。对于大型数据集,这会导致性能显着下降。有没有 elegant/simple 方法可以按照我的要求组合这些数组?
感谢您的指导!
(通常我会把它作为评论,因为它没有回答问题,但我觉得花时间解释你应该如何改变它是值得的。)
这当然是可能的,但不要这样做。答案是用结构数组替换它。根据您的数据描述:
struct Element {
let rank: Int
let name: String
let items: Set<String> // Since you seem to want them to be unique and unordered
}
let elements: [[Element]] =
[[Element(rank: 1, name: "My Name", items: ["Item1", "Item2"])],
[Element(rank: 5, name: "My Name", items: ["Item2", "Item3"]),
Element(rank: 3, name: "My Second Name", items: ["Item1"])]]
// You want to manage these by name, so let's make key/value pairs of all the elements
// as (Name, Element)
let namedElements = elements.joined().map { ([=10=].name, [=10=]) }
// Now combine them as you describe. Add the ranks, and merge the items
let uniqueElements =
Dictionary<String, Element>(namedElements,
uniquingKeysWith: { (lhs, rhs) -> Element in
return Element(rank: lhs.rank + rhs.rank,
name: lhs.name,
items: lhs.items.union(rhs.items))
})
// The result is the values of the dictionary
let result = uniqueElements.values
// Element(rank: 6, name: "My Name", items: Set(["Item3", "Item2", "Item1"]))
// Element(rank: 3, name: "My Second Name", items: Set(["Item1"]))
我用的是Swift4,Xcode9.
具体来说,我有一个数组 [[(Int, String)]] 数组,其中 Int 是一个等级,String 是一个名称 + 项目...使用 .joined(separator: ";") 组合.
数据可能如下所示:
[[1,"My Name;Item1;Item2"], [(5,"My Name;Item2;Item3"), (3,"My Second Name;Item1")]]
我想合并内部数组,以便:
- Int 添加基于名称的匹配项(最多为“;”)
- 字符串添加后续项目(如果不存在)
结合我上面的例子应该会导致:
[(6,"My Name;Item1;Item2;Item3"), (3,"My Second Name;Item1")]
即输入为 [[(Int, String)]]
,输出为 [(Int, String)]
目前,我可以通过一组相当复杂的循环来实现这一点。对于大型数据集,这会导致性能显着下降。有没有 elegant/simple 方法可以按照我的要求组合这些数组?
感谢您的指导!
(通常我会把它作为评论,因为它没有回答问题,但我觉得花时间解释你应该如何改变它是值得的。)
这当然是可能的,但不要这样做。答案是用结构数组替换它。根据您的数据描述:
struct Element {
let rank: Int
let name: String
let items: Set<String> // Since you seem to want them to be unique and unordered
}
let elements: [[Element]] =
[[Element(rank: 1, name: "My Name", items: ["Item1", "Item2"])],
[Element(rank: 5, name: "My Name", items: ["Item2", "Item3"]),
Element(rank: 3, name: "My Second Name", items: ["Item1"])]]
// You want to manage these by name, so let's make key/value pairs of all the elements
// as (Name, Element)
let namedElements = elements.joined().map { ([=10=].name, [=10=]) }
// Now combine them as you describe. Add the ranks, and merge the items
let uniqueElements =
Dictionary<String, Element>(namedElements,
uniquingKeysWith: { (lhs, rhs) -> Element in
return Element(rank: lhs.rank + rhs.rank,
name: lhs.name,
items: lhs.items.union(rhs.items))
})
// The result is the values of the dictionary
let result = uniqueElements.values
// Element(rank: 6, name: "My Name", items: Set(["Item3", "Item2", "Item1"]))
// Element(rank: 3, name: "My Second Name", items: Set(["Item1"]))