2

I have these three array :

let codesArray = ["de_DE", "en_US", "en-GB", "es_ES"]
let localesArray = ["Deutsch", "English", "English UK", "Español"]
let internationalsArray = ["German", "English", "British English", "Spanish"]

I would like to sort the internationalsArray and sort the others based on internationalsArray, so that I will obtain :

codesArraySorted = [ "en-GB",  "en_US", "de_DE", "es_ES"]
localesArraySorted = [ "English UK",  "English", "Deutsch",  "Español"]
internationalsArraySorted = ["British English", "English", "German", "Spanish"]

I tried with sort(), isOrderedBefore but no success.

Can you give me an idea ?

Thanks a lot !

3
  • 1
    Create a struct to hold your information (each country) to group en-GB with English UK then sort that array. Why do you need to manage three separate arrays? Commented Apr 10, 2016 at 12:28
  • Thank you Oliver, I need to keep arrays in order to use some of builtin methods and library... It will not work with struct or dictionaries... Commented Apr 10, 2016 at 12:32
  • You can always map an array of structs to get a new array that contains just the relevant information. Commented Apr 10, 2016 at 12:46

4 Answers 4

2

You should put this information into a custom struct. Then you can put instances of this struct type into an array and sort the array:

struct Language {
    let code: String
    let locale: String
    let international: String
}

let languages = [
    Language(code: "de_DE", locale: "Deutsch", international: "German"),
    Language(code: "en_US", locale: "English", international: "English"),
    Language(code: "en-GB", locale: "English UK", international: "British English"),
    Language(code: "es_ES", locale: "Español", international: "Spanish")
]

let sorted = languages.sort { $0.international < $1.international }
print(sorted)

You can then use the map method to extract the original information:

let codesArraySorted = sorted.map { $0.code }
let localesArraySorted = sorted.map { $0.locale }
let internationalsArraySorted = sorted.map { $0.international }
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, I implement this answer, because it is the most understandable.
1

First of all in Swift we should not name a variable (or constant) after its type, so:

let codes = ["de_DE", "en_US", "en-GB", "es_ES"]
let locales = ["Deutsch", "English", "English UK", "Español"]
let internationals = ["German", "English", "British English", "Spanish"]

Now let's build an array of indexes looking at how codes should be sorted

let indexes = codes.enumerate().sort { $0.element < $1.element }.map { $0.index }

The indexes array contains [0, 2, 1, 3], the i-th element into this array represents the position the i-th of codes should have.

So now we can sort each array based on indexes

let sortedCodes = codes.enumerate().sort { indexes[$0.0] < indexes[$1.0] }.map { $0.element }
let sortedLocales = locales.enumerate().sort { indexes[$0.0] < indexes[$1.0] }.map { $0.element }
let sortedInternationals = internationals.enumerate().sort { indexes[$0.0] < indexes[$1.0] }.map { $0.element }

Output

sortedCodes // ["de_DE", "en-GB", "en_US", "es_ES"]
sortedLocales // ["Deutsch", "English UK", "English", "Español"]
sortedInternationals // ["German", "British English", "English", "Spanish"]

That's it.

1 Comment

That is the way I was waiting for ! (used many times in Matlab)
1

You can use the zip3 function https://gist.github.com/kristopherjohnson/04dbc470e17f67f836a2#file-zip-swift if you don't want to implement your own struct or dictionary.

let codesArray = ["de_DE", "en_US", "en-GB", "es_ES"]
let localesArray = ["Deutsch", "English", "English UK", "Español"]
let internationalsArray = ["German", "English", "British English", "Spanish"]

let combined = zip3(internationalsArray, b: localesArray, c: codesArray).sort {$0.0 < $1.0}

// use map to extract the individual arrays
let internationalsArraySorted = combined.map {$0.0}
let localesArraySorted = combined.map {$0.1}
let codesArraySorted = combined.map {$0.2}

print(internationalsArraySorted)  // "["British English", "English", "German", "Spanish"]\n"
print(localesArraySorted)  // "["English UK", "English", "Deutsch", "Español"]\n"
print(codesArraySorted)  // "["en-GB", "en_US", "de_DE", "es_ES"]\n"

4 Comments

Thank you, but I did not fully undestand this zip3 function, due to its lack of documentation. Maybe it is a well known feature in other languages
Zip is also included in Swift. swiftdoc.org/v2.2/func/zip. It tells that the 1st element of all arrays are related like de_DE, Deutsch and German are one component. It is used to solve exactly what your trying to ache with just one line of code. Its a type functional paradigm.
it is look like combine multiples arrays into a structure, interesting !
Yea it is a functional way of solving problem. The other two answers does the same.
1

Here's another way to do it that avoids sorting multiple times and will also allow you to update your original variables if you want to:

var codes = ["de_DE", "en_US", "en-GB", "es_ES"]
var locales = ["Deutsch", "English", "English UK", "Español"]
var internationals = ["German", "English", "British English", "Spanish"]

(codes,locales,internationals) = {( $0.map{codes[$0]}, 
                                    $0.map{locales[$0]}, 
                                    $0.map{internationals[$0]} 
                                 )} 
(codes.enumerated().sorted{$0.1<$1.1}.map{$0.0}) 

[EDIT] You may also want to check out this answer: https://stackoverflow.com/a/35274250/5237560 for a more elegant notation.

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.