4

For example say I have an array like so:

var someArray = ["1", "1", "2"]

I need to put this into two arrays that look like:

["1","1"]

["2"]

How can I go about this?

Any help would be great!

3 Answers 3

6

Use Dictionary initializer init(grouping:by:) Then just get arrays by accessing values property.

Example:

let dic = Dictionary(grouping: someArray) { $0 }
let values = Array(dic.values)
print(values)

Result:

[["2"], ["1", "1"]]
Sign up to request clarification or add additional context in comments.

8 Comments

This is the best way. He's using O(N) runtime complexity to match the objects compared to @Bruno 's implementation which uses O(N*N)
@kirander remove .first!. If he's working with Strings, first would group numbers like "1" and "12" together
My initial down vote was due to it being a link only post. Now this is definitely my favourite method :D
on the first line, i get an error Generic parameter 'key' could not be inferred
Show us how you declared the array
|
3

Here are some facts (the upvote and answer should go to @kirander)

With @kirander method's is using the Dictionary to map the objects in a O(N) runtime and O(N) memory.

The other solutions are mostly running in O(N*N) runtime and O(N) memory. Because of this, grouping a random array of 1000 items will take: 0.07s with @kirander solution and 34s. with other solutions.

func benchmark(_ title:String, code: ()->()) {
  let startTime = CFAbsoluteTimeGetCurrent()
  code()
  let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
  print("Time elapsed for \(title): \(timeElapsed) s.")
}

var array:[String] = []
for _ in 0...1000 {
  array.append("\(Int(arc4random_uniform(10)))")
}

// @kirander solution 0.07s
benchmark("Dictionary", code: {

  let dic = Dictionary(grouping: array, by: { $0 })
  let values = Array(dic.values)
})


// @Bruno solution ~34s
benchmark("Array", code: {
  var resultingArrays = [[String]]()
  for value in array {
    let ar = array.filter({ $0 == value })
    if !resultingArrays.contains(where: {$0 == ar}) {
      resultingArrays.append(ar)
    }
  }
})

2 Comments

Interesting to see how the solutions scale. Thank you for that!
I'm getting an compile time error Generic parameter 'key' could not be inferred for @kirander solution.
1

You could try something like this:

var someArray = ["1", "1", "2"]

var resultingArrays = [[String]]()

for value in someArray {
    let array = someArray.filter({ $0 == value })
    if !resultingArrays.contains(where: {$0 == array}) {
        resultingArrays.append(array)
    }
}

2 Comments

@kirander's comment was edited. Now I agree that his answer is the more efficient and better one.
@RobertD.Mogos Its my opinion you may have different opinion. Because when i commented on this answer that time no one given proper answer. So according to me it is best answer.

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.