1

I have 2 arrays. Inside the first array I have a namelist that I want to remove from second array.

First array is simply array of strings:

var arrayNames = ["apple", "apricot", "cucumber"]

Second array is an array of custom structs:

struct fruitsData {
var name: String?
}

var secondArray = [fruitsData(name: "apple"),fruitsData(name: "apricot"), fruitsData(name: "mango"), fruitsData(name: "grapes"), fruitsData(name: "tomato"), fruitsData(name: "lichi"), fruitsData(name: "cucumber"), fruitsData(name: "brinjal")]

So how could I get the array which contains this data only:

var finalData = [fruitsData(name: "mango"), fruitsData(name: "grapes"), fruitsData(name: "tomato"), fruitsData(name: "lichi"), fruitsData(name: "brinjal")]

which does not include any name from arrayNames?

1
  • It would be nice to see your feedback about our answers. Commented May 21, 2017 at 8:49

5 Answers 5

1

There are a couple of ways to do this:

  • the best way is using a filter method:

    var arrayNames = ["apple", "apricot", "cucumber"]
    var secondArray = [fruitsData(name: "apple"),fruitsData(name: "apricot"), fruitsData(name: "mango"), fruitsData(name: "grapes"), fruitsData(name: "tomato"), fruitsData(name: "lichi"), fruitsData(name: "cucumber"), fruitsData(name: "brinjal")]
    
    secondArray = secondArray.filter({$0.name != nil && !arrayNames.contains($0.name!)})
    
  • alternatively, if you want to sacrifice efficiency for the sake of readability, you can use a for-in loop alongside a helper Array:

    var arrayNames = ["apple", "apricot", "cucumber"]
    var secondArray = [fruitsData(name: "apple"),fruitsData(name: "apricot"), fruitsData(name: "mango"), fruitsData(name: "grapes"), fruitsData(name: "tomato"), fruitsData(name: "lichi"), fruitsData(name: "cucumber"), fruitsData(name: "brinjal")]
    var helperArray = [fruitsData]()
    
    for fruit in secondArray {
    
        if fruit.name != nil && !arrayNames.contains(fruit.name!){
            helperArray.append(fruit)
        }
    
    }
    
    secondArray = helperArray
    

The above will erase every element from secondArray whose name is contained by arrayNames. You should familiarise yourself with Map, Filter and Reduce.

Sign up to request clarification or add additional context in comments.

Comments

1

Your finalData from secondArray excluding arrayNames can be achieved here . .

var finalData = secondArray.filter { !arrayNames.contains($0.name!)}

Comments

0

I am on the phone so I can't check it, but this should do the trick

secondArray.filter { !firstArray.contains($0.name) }

Comments

0

If the name is NOT expected to be an empty string, you can use

let arrayNames = ["apple"]

struct fruitsData {
    var name: String?
}
var secondArray = [fruitsData(name: "apple"),fruitsData(name: "apricot"), fruitsData()]

// [__lldb_expr_98.fruitsData(name: Optional("apple"))]
let flt1 = secondArray.filter { arrayNames.contains($0.name ?? "") }

// [__lldb_expr_87.fruitsData(name: Optional("apricot")), __lldb_expr_87.fruitsData(name: nil)]
let flt2 = secondArray.filter { !arrayNames.contains($0.name ?? "") }

Comments

0

The natural approach when wanting to construct a subset array from a given array and some predicate is using filter. Since name of the FruitsData struct is an Optional, you'll need to (attempt to) unwrap it prior to comparing it to the non-Optional names in the arrayNames list, e.g. using the map(_:) method of Optional along with optional chaining for handling nil-valued name cases.

E.g.:

// example setup
struct FruitsData {
    var name: String?
}

let arrayNames = ["apple", "apricot", "cucumber"]

let secondArray = [
    FruitsData(name: "apple"),    FruitsData(name: "apricot"),
    FruitsData(name: "mango"),    FruitsData(name: "grapes"),
    FruitsData(name: "tomato"),   FruitsData(name: "lichi"),
    FruitsData(name: "cucumber"), FruitsData(name: "brinjal")
]

// filter 'secondArray' based on the non-existance of an
// associated fruit name in the 'arrayNames' list
let finalData = secondArray.filter {
    $0.name.map { fruitName in !arrayNames.contains(fruitName) } ?? true
}

Since String conforms to Hashable, you might also want to consider letting the list of fruit names to be excluded (arrayNames) be a Set rather than an Array, as the former will allow O(1) lookup when applying contains { ... } to it. E.g.:

let removeNames = Set(arrayNames)
let finalData = secondArray.filter {
    $0.name.map { fruitName in !removeNames.contains(fruitName) } ?? true
}                                        /* ^^^^^^^^- O(1) lookup */

If you'd also like to filter out FruitsData instances in secondArray that have nil valued name properties, you can simply with the ... ?? true predicate part above to ... ?? false: the filter operation will then filter out all FruitsData instances whose name property is either nil or present in arrayNames.

// ... filter out also FruitsData instances with 'nil' valued 'name'
let removeNames = Set(arrayNames)
let finalData = secondArray.filter {
    $0.name.map { fruitName in !removeNames.contains(fruitName) } ?? false
}

3 Comments

your solution will return all FruitsData where name == nil what is not expected.
@user3441734 I believe OP specified that only FruitsData instances where the name is also present in the non-optional [String] array arrayNames should be filtered out from the FruitsData array. This would correspond to the expected result that FruitsData instances with nil valued name instances are to be kept in the filtered FruitsData arrays. If, on the other hand, also nil objects are to be removed (which has not been specified by OP), it is a simple matter of replacing the ... ?? true with ... ?? false in the predicate to filter above.
Yes, that works. Unfortunately, inverse your function is not easy, so you have to decide how to process data with nil names separately.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.