通过价值拆分为数组的数组Swift

标签: ios Swift
发布时间: 2017/3/6 23:03:15
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

我有数组他们包含这样的数据: [值] #[模式] (模式是可选的)

我想要拆分此阵列到阵列 [价值] 的 [模式],但保持同样的位置数据,这样可以为相同的模式很多数组︰

前︰

let array = ["23.88", "24", "30",  "24.16#C", "25#C", "12#C", "24.44#O", "50#O" , "31", "40" , "44#C", "55#C"]  

// Result 

No mode  ---> [23.88,24,30] 
mode = C ---> [24.16,25,12]
mode = O ---> [24.44,50]
No mode  ---> [31,40] 
mode = C ---> [44,55]

尝试此扩展,但不是我想要

extension SequenceType {
    func groupBy<U : Hashable>(@noescape keyFunc: Generator.Element -> U) -> [U:[Generator.Element]] {
        var dict: [U:[Generator.Element]] = [:]
        for el in self {
            let key = keyFunc(el)
            if case nil = dict[key]?.append(el) { dict[key] = [el] }
        }
        return dict
    }
}

它给我这样的结果︰

No mode  ---> [23.88,24,30,31,40] 
mode = C ---> [24.16,25,12,44,55]
mode = O ---> [24.44,50] 

解决方法 1:

您需要修改 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])] */

或者︰ 组和清理单链式调用中的模式标记

或者,两个 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 值案例。)

官方微信
官方QQ群
31647020