2

Say I had two arrays:

var arrayA = ["Yes", "Yes2", "Not Answered", "No"]
var arrayB = ["Yes", "NA", "Yes2", "NA"]

And I wanted to remove the "NA"s from arrayB by doing:

var filtered = arrayB.filter({$0 != "NA"})

How could I remove the items at the same indexes removed in arrayA. I thought about using the find() function, but that only returns the first index a string appears. You can remove overlap from the arrays by:

let res = arrayA.filter { !contains(arrayB, $0) }

but how could I filter an array based on the filtering of another array?

the result would have:

arrayBFiltered = ["Yes", "Yes2"]
arrayAFiltered = ["Yes", "Not Answered"]

Any ideas?

modesitt
  • 7,052
  • 2
  • 34
  • 64
  • You have accepted the answer I would consider the least "swift" way and the hackiest way. @Matteo's method is much nicer and much more "swifty". I do wonder why you don't have a data model to hold these data though? If they are so closely related then you should have them in a single model. – Fogmeister Jul 07 '15 at 13:10

3 Answers3

6

You might prefer using zip:

var arrayA = ["Yes", "Yes2", "Not Answered", "No"]
var arrayB = ["Yes", "NA", "Yes2", "NA"]

let result = filter(zip(arrayA, arrayB)) { (a, b) in b != "NA" }

for (a, b) in result {
    println("A: \(a) -> B: \(b)")
}

EDIT: SWIFT 2.0

In Swift 2.0 it will be even easier to obtain an array of a consolidated ad-hod struct (say ... Foo) for clearer subsequent code:

struct Foo {
    let a: String
    let b: String
}
// Foo.init will be the function automatically generated by the default initialiser

let result = zip(arrayA, arrayB)
    .filter { (a, b) in b != "NA" }
    .map(Foo.init)
// Order of a and b is important

// result is an Array<Foo> suitable for a clearer subsequent code
for item in result {
    print("A: \(item.a) -> B: \(item.b)")
}

Hope this helps

Matteo Piombo
  • 6,688
  • 2
  • 25
  • 25
1

The ideas from How can I sort multiple arrays based on the sorted order of another array could be used here, that would work for two or more arrays:

let arrayA = ["Yes", "Yes2", "Not Answered", "No"]
let arrayB = ["Yes", "NA", "Yes2", "NA"]

// Determine array indices that should be kept:
let indices = map(filter(enumerate(arrayB), { $1 != "NA" } ), { $0.0 } )

// Filter arrays based on the indices:
let arrayAFiltered = Array(PermutationGenerator(elements: arrayA, indices: indices))
let arrayBFiltered = Array(PermutationGenerator(elements: arrayB, indices: indices))

println(arrayAFiltered) // [Yes, Not Answered]
println(arrayBFiltered) // [Yes, Yes2]
Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
0

Another solution would be to make the remove code directly inside the filter closure:

// both are vars so you can mutate them directly
var arrayA = ["Yes", "Yes2", "Not Answered", "No"]
var arrayB = ["Yes", "NA", "Yes2", "NA"]

arrayA = filter(enumerate(arrayA)){
    arrayB.removeAtIndex($0)
    return $1 != "Na"
}

// use filtered arrayA and arrayB
Qbyte
  • 12,753
  • 4
  • 41
  • 57