有没有办法在过滤器后拆分数组

时间:2018-12-28 11:31:41

标签: arrays filter swift4.2

我发现自己遇到了麻烦,必须将数组分为两个数组。一个仅包含价格,另一个仅包含描述。

例如:

var startingArray = ["apple", "30.00", "pizza", "2.00"]

结果应该是:

var firstArray = ["apple", "pizza"]
var secondArray = ["30.00", "2.00"]

Swift 4.2

有没有办法达到这个结果? 预先感谢

5 个答案:

答案 0 :(得分:1)

您不想要这种结果。
apple30.00在一起。 pizza2.00在一起。
如果使用这两个数组,则如果更改顺序,则删除一个,则需要对第二个数组执行相同的操作。

使用字典数组代替

let startingArray = ["apple", "30.00", "pizza", "2.00"]
var final: [[String: String]] = []
for i in stride(from: 0, to: startingArray.count, by: 2) {
   let name = startingArray[i]
    let price = startingArray[i+1]
    final.append(["name": name, "price": price])
}
print("final: \(final)")

输出:

$> [["name": "apple", "price": "30.00"], ["name": "pizza", "price": "2.00"]]

然后,您可以对最终数组进行操作:

let first: [String: String] = final[0]
let firstName = first[name]
let firstPrice = first[price]

您也可以使用元组,但是更好的方法是使用自定义struct / class来表示它。

struct Grocery {
    let name: String
    let price: Double
    init(name: String, priceStr: String) {
        self.name = name
        self.price = Double(priceStr) ?? 0
    }
}

let startingArray = ["apple", "30.00", "pizza", "2.00"]
var groceries = [Grocery]()
for i in stride(from: 0, to: startingArray.count, by: 2) {
    let name = startingArray[i]
    let price = startingArray[i+1]
    let grocery = Grocery(name: name, priceStr: price)
    groceries.append(grocery)
}
print("groceries: \(groceries)")

输出:

$> groceries: [Grocery(name: "apple", price: 30.0), Grocery(name: "pizza", price: 2.0)]

然后,您可以对最终数组进行操作:

let first: Grocery = groceries[0]
let firstName = first.name
let firstPrice = first.price

注意:我使用Double作为价格,但是如果您希望将其保留为String,则取决于您。

答案 1 :(得分:0)

您可以尝试如下操作:

extension Array {
    func separate() -> (odd: [Element], even: [Element]) {
        return self.reduce(into: (odd: [], even: [])) { (acc, element) in
            if (acc.even.count + acc.odd.count) % 2 == 0 {
                acc.odd.append(element)
            } else {
                acc.even.append(element)
            }
        }
    }
}

let startingArray = ["apple", "30.00", "pizza", "2.00"]

let (firstArray, secondArray) = startingArray.separate()
print(firstArray) // ["apple", "pizza"]
print(secondArray) // ["30.00", "2.00"]

使用此方法,您可以将数组元素组合成字典:

extension Array where Element: Hashable {
    func dictionaryWithOddEvenRule(uniquingKeysWith combine: (Element, Element) throws -> Element) rethrows -> [Element: Element] {
        let (keys, values) = self.separate()
        let sequence = zip(keys, values)
        return try Dictionary(sequence, uniquingKeysWith: combine)
    }
}

甚至在一般情况下:

extension Array {
    func dictionaryWithOddEvenRule<K, V>(keysTransform: (Element) throws -> K, valueTransform: (Element) throws -> V, uniquingKeysWith combine: (V, V) throws -> V) rethrows -> [K: V] where K: Hashable {
        let (keys, values) = self.separate()
        let sequence = zip(try keys.map(keysTransform), try values.map(valueTransform))
        return try Dictionary.init(sequence, uniquingKeysWith: combine)
    }
}

例如:

enum ExampleError: Error {
    case cantParseDouble
}

do {
    let result: [String: Double] = try startingArray.dictionaryWithOddEvenRule(
        keysTransform: { $0 }, // Transform between array element type to dictionary key type
        valueTransform: {
            // Transform between array element type to dictionary value type
            if let double = Double($0) {
                return double
            } else {
                throw ExampleError.cantParseDouble
            }
        },
        uniquingKeysWith: {
            ($0 + $1)/2 // Handle situation when two identical keys exist 
        }
    )
    print(result) // Handle result
} catch let error {
    print(error) // Handle error
}

答案 2 :(得分:0)

您可以使用forEach功能来实现此目的。

在声明了startingArray之后,将另外两个Strings和Doubles数组声明为:

var doubleArray = [String]()
var stringArray = [String]()

然后使用forEach来启动array来分隔元素并相应地添加如下内容:

    startingArray.forEach { (element) in
        if let _ = Double(element) {
            doubleArray.append(element)
        } else {
            stringArray.append(element)
        }
    }

打印阵列时,结果将显示为单独:

    print(doubleArray)
    print(stringArray)

答案 3 :(得分:0)

尝试使用

步幅: 推荐

let f1 = stride(from: 1, to: startingArray.count, by: 2).map({ startingArray[$0] })
let f2 = stride(from: 0, to: startingArray.count, by: 2).map({ startingArray[$0] })

过滤器:

let f1 = startingArray.filter({ Double($0) != nil })
let f2 = startingArray.filter({ !f1.contains($0) })

答案 4 :(得分:0)

您可以这样操作:

var startingArray = ["apple", "30.00", "pizza", "2.00"]

var firstArray: [String] = []
var secondArray: [String] = []

for str in startingArray {
    if let _ = Double(str) {
        firstArray.append(str)
    } else {
        secondArray.append(str)
    }
}

print(firstArray)   //["30.00", "2.00"]
print(secondArray)  //["apple", "pizza"]

但是正如Larme所建议的那样,您最好在方法上更加面向对象,并使用例如structs

struct Fruit {
    let name: String
    let price: Double
}

var startingArray = ["apple", "30.00", "pizza", "2.00"]

let zipped = zip(startingArray, startingArray.dropFirst())

var fruitArray = [Fruit]()

for couple in zipped {
    let name = couple.0
    if let price = Double(couple.1) {
        let fruit = Fruit(name: name, price: price)
        fruitArray.append(fruit)
    }
}