-1

let's say I have an array this way : [1,4,7,4,2,2,4,7,1,2].

I need a function that divides this array into arrays with the same elements so it shows a result as this in swift :

result = [[1,1],[4,4,4],[7,7],[2,2,2]] .

How to do that in swift ? Thanks in advance

Léo Natan
  • 56,823
  • 9
  • 150
  • 195
  • 1
    Take a look at [How to group by the elements of an array in Swift](http://stackoverflow.com/questions/31220002/how-to-group-by-the-elements-of-an-array-in-swift) – which will generate a dictionary of grouped elements. From there it's a short step to get an array of the groupings. – Hamish Nov 04 '16 at 13:32
  • @Hamish the problem is in that case , he has only dinner or launch so he knows the number of filterArrays , but in my case , I don't know the number of filterArrays, that array is just an exemple . – Aymen Bromdhane Nov 04 '16 at 13:34
  • Take a look at the answer, not the question. The answer works for any number of groupings. – Hamish Nov 04 '16 at 13:35
  • Tanks Hamich :) – Aymen Bromdhane Nov 04 '16 at 13:50

2 Answers2

1

You can use a helper dictionary to categorize the values of your array into the appropriate bins. E.g.:

let arr = [1, 4, 7, 4, 2, 2, 4, 7, 1, 2]
var dict: [Int: [Int]] = [:]
arr.forEach { dict[$0] = (dict[$0] ?? []) + [$0] }
let inBins = dict.map{ $1 }.sorted{ $0.first ?? 0 < $1.first ?? 0 }
print(inBins) // [[1, 1], [2, 2, 2], [4, 4, 4], [7, 7]]

Or, make use of the general Sequence extension for the categorising part, as described in the accepted answer in thread linked to by @Hamish:

E.g.:

/* from https://stackoverflow.com/a/39388832/4573247:
   @mientus's Swift 3 translation of @oisdk's accepted answer */
public extension Sequence {
    func categorise<U : Hashable>(_ key: (Iterator.Element) -> U) -> [U:[Iterator.Element]] {
        var dict: [U:[Iterator.Element]] = [:]
        for el in self {
            let key = key(el)
            if case nil = dict[key]?.append(el) { dict[key] = [el] }
        }
        return dict
    }
}

let arr = [1, 4, 7 ,4, 2, 2, 4, 7, 1, 2]
let inBins = arr.categorise{ $0 }.map{ $1 }.sorted{ $0.first ?? 0 < $1.first ?? 0 }
print(inBins) // [[1, 1], [2, 2, 2], [4, 4, 4], [7, 7]]

No need for the bins to be sorted (as above)? The two options above are then reduced to (simply dropping the last sortin part):

// ... first alternative above
let inBins = dict.map{ $1 }

// ... 2nd alternative above
let inBins = arr.categorise{ $0 }.map{ $1 }
Community
  • 1
  • 1
dfrib
  • 70,367
  • 12
  • 127
  • 192
  • Note that I don't *believe* OP requires the result to be sorted ;) – Hamish Nov 04 '16 at 13:46
  • @Hamish ah you're right, I only read the first element, `[[1, 1] , [blind], [as], [for], [the], [rest]]`, thanks! – dfrib Nov 04 '16 at 13:47
0

Another option could be to create an NSCountedSet:

let array = [1,4,7,4,2,2,4,7,1,2]
let countedSet = NSCountedSet(array: array)

You could then easily get the count of each unique element:

let countForOne = countedSet.count(for: 1)

As far as I know there is no native Swift equivalent of NSCountedSet yet.

koen
  • 5,383
  • 7
  • 50
  • 89