Вам нужно изменить groupBy
расширение для группы в массив 2-кортежей, а не словарь, в котором первый элемент кортежа соответствует неспецифическому «ключу», а второй элемент кортежа представляет собой массив последующих элементов массива self
, который может быть отнесен к данному ключу.
Модифицированный SequenceType
расширение
extension SequenceType {
func groupBy<U : Comparable>(@noescape keyFunc: Generator.Element -> U) -> [(U,[Generator.Element])] {
var tupArr: [(U,[Generator.Element])] = []
for el in self {
let key = keyFunc(el)
if tupArr.last?.0 == key {
tupArr[tupArr.endIndex-1].1.append(el)
}
else {
tupArr.append((key,[el]))
}
}
return tupArr
}
}
Отметим также, что в настоящее время достаточно, чтобы в расширении родовое U
соответствует Comparable
, так как мы используем только U
элементы, как «поддельные» ключей в кортеже ,
призыв к расширению
С этой модификации, мы можем вызвать метод groupBy(..)
, как
let array = ["23.88", "24", "30", "24.16#C", "25#C", "12", "24.44", "50" , "31#O", "40#O" , "44#C", "55#C"]
/* assuming we know the last character always describe the mode,
given one is included (#) */
let groupedArray: [(String,[String])] = array.groupBy {
guard $0.characters.contains("#") else { return "No mode" }
return "mode = " + String($0.characters.last!)
}
print(groupedArray)
/* [("No mode", ["23.88", "24", "30"]),
("mode = C", ["24.16#C", "25#C"]),
("No mode", ["12", "24.44", "50"]),
("mode = O", ["31#O", "40#O"]),
("mode = C", ["44#C", "55#C"])] */
Удаление оригинальных режима маркировки (#X
) из сгруппированных массива
Если вы как удалить исходные метки режима (#X
) в результирующем массиве, вы можете применить дополнительную операцию map
после вызова groupBy
.
Удаление маркировки с результирующих значений, как String
:
let groupedArrayClean = groupedArray.map { ($0.0, $0.1.map {
String($0.characters.prefixUpTo($0.characters.indexOf("#") ?? $0.characters.endIndex))
})
}
print(groupedArrayClean)
/* [("No mode", ["23.88", "24", "30"]),
("mode = C", ["24.16", "25"]),
("No mode", ["12", "24.44", "50"]),
("mode = O", ["31", "40"]),
("mode = C", ["44", "55"])] */
Или, с результирующих значений, как Double
:
let groupedArrayClean = groupedArray.map { ($0.0, $0.1.flatMap {
Double(
String(($0.characters.prefixUpTo($0.characters.indexOf("#") ?? $0.characters.endIndex))))
})
}
print(groupedArrayClean)
/* [("No mode", [23.879999999999999, 24.0, 30.0]),
("mode = C", [24.16, 25.0]),
("No mode", [12.0, 24.440000000000001, 50.0]),
("mode = O", [31.0, 40.0]),
("mode = C", [44.0, 55.0])] */
В качестве альтернативы: группы и очистки режима маркировки в одном прикованного вызова
Или, b groupBy
др следует map
сразу, без промежуточного задания:
let groupedArrayClean: [(String,[String])] = array.groupBy {
guard $0.characters.contains("#") else { return "No mode" }
return "mode = " + String($0.characters.last!)
}
.map { ($0.0, $0.1.map {
String($0.characters
.prefixUpTo($0.characters.indexOf("#") ?? $0.characters.endIndex))
})
}
(аналогично для полученного значения Double
случая.)
Я попытался расширение GroupBy но не то, что я хочу. Я обновил свой пост – OuSS
Swift словари требуют, чтобы ключи были уникальными. Если вы хотите сгенерировать свои результаты с помощью словаря так, как вы их разбили, вам нужно будет иметь карту ключей для массива массивов. –
Помогите мне – OuSS