4

Im new to swift and would appreciate your help..

Problem:

In my future project I would love to look for a specific String in an Array and get only the names back who have this value in their hobbies Array.

My example:

struct Person {
var name: String
var hobbies:Set <String>
}

var persons: [Person]

persons = [

Person(name: "Steve", hobbies: ["PC", "PS4", "Gaming", "Basketball"]),
Person(name: "Max", hobbies: ["Gaming", "Xbox", "cooking", "PC"]),
Person(name: "Julia", hobbies: ["Soccer", "Tennis", "cooking", "Painting"])

]

var StringToSearch = "PC"

I would love to get only the names back who hobbies "PC" is. How can I iterate through my collection and get only the keys instead of the values back like in a dictionary? Thank you!

6 Answers 6

4

Use flatMap:

let result = persons.flatMap {
    $0.hobbies.contains(StringToSearch) ? $0.name : nil
}
Sign up to request clarification or add additional context in comments.

13 Comments

There's more than one way to skin the cat. flatMap acts as a nil-filter. contains acts as the hobby-check. And the requirement is "only the names back"
I like this solution. Unlike the answers that combine filter + map, this makes a single pass over the data.
@vacawama No idea, one of them is mine though :) I guess the lack of explanation is (understandably) holding people back, although it's the still the best solution to the problem.
@vacawama Yes, that appears to be the case (you can click on the score to see the vote breakdown) – although I couldn't say why. Lack of explanation on an otherwise spot-on answer isn't worthy of a downvote imo.
Could be the lack of explanation. It wouldn't hurt to point out how flatMap works and why it is more efficient than filter + map.
|
3

you can use filter + map to return name array of all people who have "PC" hobbies:

let nameArray = persons.filter{$0.hobbies.contains("PC")}.map{$0.name}
//return ["Steve", "Max"]

Comments

3

Using filter(_:)

let stringToSearch = "PC"
let pcHobbiests = persons.filter { $0.hobbies.contains(stringToSearch) }
let pcHobbiestNames = persons.map { $0.name }

Explaination

filter(_:) will iterate over elements of a Sequence, building up a new Array containing only those elements for which closure evaluates to true. In this instance, the closure checks if the hobbies Array of the currently iteration's Person contains stringToSearch.

You can then iterate over your pcHobbiests Array or use them as you please:

for pcHobbiest in pcHobbiests {
    print(pcHobbiest)
}

Comments

2

Using reduce

After map, filter and flatMap here's my solution with reduce :)

let names = persons.reduce([String]()) { (names, person) -> [String] in
    guard person.hobbies.contains(keyword) else { return names }
    return names + [person.name]
}

One liner (but don't do it at home!)

And if your really want to write everything on 1 line...

let names = persons.reduce([String]()) { $0.0 + ($0.1.hobbies.contains(keyword) ? [$0.1.name] : []) }

2 Comments

;) nice code with reduce on one line. I give a up-vote but I must say that reduce solution is not very easy to read and understand :|
@HoaParis: I totally agree but the other solutions were already taken :D
1

Use Swift's for-in loop.

for pers in persons {
    if pers.hobbies.contains(StringToSearch) {
        nameOfPCGamer = pers.name
    }
}

2 Comments

This solution is not building a list of names matching ALL the persons with a specific hobby. It is just saving the name for the last person with that hobby instead.
I was just showing how to get all of them. Handling the data inside of the if statement up to whoever to figure out.
-2

You may use a loop, collect:

for p in persons {
  if p.hobbies.contains("PC") {
    // then you've got one!
  }
}

or you can use a more generic programming by filtering the array, thus obtaining an array of filtered content and iterating on it:

for p in persons.filter({$0.hoobies.contains("PC")}) {
  // got one...
}

Comments

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.