Есть ли способ разделить массив после фильтра - PullRequest
0 голосов
/ 28 декабря 2018

У меня проблемы с массивом, который нужно разделить на два массива.Один только содержит цены, а другой только описания.

Например:

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

И результат должен быть:

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

Swift 4.2

Есть ли способ достичь этого результата?Заранее спасибо

Ответы [ 5 ]

0 голосов
/ 28 декабря 2018

Вы не хотите такого результата.
apple подразумевается с 30.00.pizza подразумевается с 2.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 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, вам решать.

0 голосов
/ 28 декабря 2018

Вы можете сделать это следующим образом:

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"]

Но, как предполагает Ларме, вам лучше быть более объектно-ориентированным в своем подходе и использовать, например, структуры:

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)
    }
}
0 голосов
/ 28 декабря 2018

Этого можно добиться, используя функциональность forEach.

После объявления вашего стартового массива объявите два других массива для строк и двойников как:

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

Затем используйте forEach дляначальный массив для разделения ваших элементов и добавления соответственно следующим образом:

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

Когда вы распечатаете свои массивы, вы увидите результаты как отдельные:

    print(doubleArray)
    print(stringArray)
0 голосов
/ 28 декабря 2018

попробуйте использовать

, шаг: Рекомендуется

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) })
0 голосов
/ 28 декабря 2018

Вы можете попробовать что-то вроде этого:

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
}
...