1

i am trying to order an array alphabetically and by group name's

My list is:

Name: A
Group: cats

Name: B
Group: dogs

Name: C
Group: cats

I have done the alphabetical order ordered by Name and it's showing me the following order:

A
cats

B
dogs

C
cats

But i'm having a migraine trying to sort them by the group, ex:

A
cats

C
cats

B
dogs

What i tried so far for alphabetical order and groups order:

case alpha:
    results.sorted { $0.first_name < $1.first_name }
case grouped:
    results.sorted { $0.group_name == $1.group_name }
6
  • You need a single sort operation. In the closure, If the names are the same then compare by group otherwise compare by name Commented Sep 9, 2018 at 21:04
  • I have a segmented control where i can select the type of the sort, so it does not help me to make it in a single sort operation. Commented Sep 9, 2018 at 21:07
  • So you may need multiple, single sort operations based on the segmented control (and it helps if you put all of your goals in your question), but the way you have it now the first sort is overridden by the second sort. You need to consider both criteria in the one sort operation. Commented Sep 9, 2018 at 21:09
  • Your second sort closure isn't even valid as it doesn't perform a relative comparison Commented Sep 9, 2018 at 21:10
  • Ok, i edited my question now. Commented Sep 9, 2018 at 21:14

2 Answers 2

7

Try this:

results.sorted {($0.group_name, $0.first_name) < ($1.group_name, $1.first_name)}

Example:

struct Item {
    var first_name: String
    var group_name: String
}

let results = [
    Item(first_name: "A", group_name: "cats"),
    Item(first_name: "B", group_name: "dogs"),
    Item(first_name: "C", group_name: "cats")
]
let sortedResult = results.sorted {($0.group_name, $0.first_name) < ($1.group_name, $1.first_name)}
print(sortedResult)
//->[SortGroups.Item(first_name: "A", group_name: "cats"), SortGroups.Item(first_name: "C", group_name: "cats"), SortGroups.Item(first_name: "B", group_name: "dogs")]

An example where Carpsen90's current code fails.

struct Animal {
    let Name: String
    let Group: String
}

let animals = [
    Animal(Name: "B", Group: "rats"),
    Animal(Name: "C", Group: "dogs"),
    Animal(Name: "E", Group: "cats"),
    Animal(Name: "B", Group: "dogs"),
    Animal(Name: "A", Group: "cats"),
    Animal(Name: "C", Group: "dogs"),
    Animal(Name: "E", Group: "cats"),
    Animal(Name: "A", Group: "dogs"),
    Animal(Name: "B", Group: "dogs"),
    Animal(Name: "B", Group: "dogs"),
    Animal(Name: "D", Group: "cats"),
    Animal(Name: "A", Group: "cats"),
    Animal(Name: "B", Group: "cats"),
    Animal(Name: "B", Group: "dogs"),
    Animal(Name: "D", Group: "rats"),
    Animal(Name: "A", Group: "rats"),
    Animal(Name: "B", Group: "dogs"),
    Animal(Name: "D", Group: "dogs"),
    Animal(Name: "A", Group: "dogs"),
    Animal(Name: "A", Group: "rats")
]

let result = animals.sorted(by: {$0.Group < $1.Group}).sorted(by: {$0.Group == $1.Group && $0.Name < $1.Name })
print("[\n  "+result.map {String(describing: $0)}.joined(separator: ",\n  ")+"\n]")

Output:

[
  Animal(Name: "E", Group: "cats"),
  Animal(Name: "A", Group: "dogs"),
  Animal(Name: "A", Group: "dogs"),
  Animal(Name: "B", Group: "dogs"),
  Animal(Name: "B", Group: "dogs"),
  Animal(Name: "B", Group: "dogs"),
  Animal(Name: "B", Group: "dogs"),
  Animal(Name: "B", Group: "dogs"),
  Animal(Name: "C", Group: "dogs"),
  Animal(Name: "C", Group: "dogs"),
  Animal(Name: "A", Group: "cats"),
  Animal(Name: "B", Group: "cats"),
  Animal(Name: "D", Group: "cats"),
  Animal(Name: "E", Group: "cats"),
  Animal(Name: "D", Group: "dogs"),
  Animal(Name: "A", Group: "cats"),
  Animal(Name: "A", Group: "rats"),
  Animal(Name: "A", Group: "rats"),
  Animal(Name: "B", Group: "rats"),
  Animal(Name: "D", Group: "rats")
]

Using tuple comparison for the same input:

let result2 = animals.sorted {($0.Group, $0.Name) < ($1.Group, $1.Name)}
print("[\n  "+result2.map {String(describing: $0)}.joined(separator: ",\n  ")+"\n]")

Output:

[
  Animal(Name: "A", Group: "cats"),
  Animal(Name: "A", Group: "cats"),
  Animal(Name: "B", Group: "cats"),
  Animal(Name: "D", Group: "cats"),
  Animal(Name: "E", Group: "cats"),
  Animal(Name: "E", Group: "cats"),
  Animal(Name: "A", Group: "dogs"),
  Animal(Name: "A", Group: "dogs"),
  Animal(Name: "B", Group: "dogs"),
  Animal(Name: "B", Group: "dogs"),
  Animal(Name: "B", Group: "dogs"),
  Animal(Name: "B", Group: "dogs"),
  Animal(Name: "B", Group: "dogs"),
  Animal(Name: "C", Group: "dogs"),
  Animal(Name: "C", Group: "dogs"),
  Animal(Name: "D", Group: "dogs"),
  Animal(Name: "A", Group: "rats"),
  Animal(Name: "A", Group: "rats"),
  Animal(Name: "B", Group: "rats"),
  Animal(Name: "D", Group: "rats")
]
Sign up to request clarification or add additional context in comments.

2 Comments

($0.group_name, $0.first_name) < ($1.group_name, $1.first_name) Is this tuple < tuple? Haven't seen that before.
@Fabian, Please check SE-0015 Tuple comparison operators.
-1

Try this

struct Animal {
    let Name: String
    let Group: String
}

let a1 = Animal(Name: "A", Group: "cats")
let a2 = Animal(Name: "B", Group: "dogs")
let a3 = Animal(Name: "C", Group: "cats")

let animals = [a3, a2, a1]

let result = animals.sorted(by: {$0.Group < $1.Group}).sorted(by: {$0.Group == $1.Group && $0.Name < $1.Name })
result  //Prints [{Name "A", Group "cats"}, {Name "C", Group "cats"}, {Name "B", Group "dogs"}]

sorted returns a new array (result) and doesn't sort the initial array (animals) in place.

9 Comments

My code actually does this on another array(a new one), the problem in my case was with a bad string key.. the above code works well
Glad I could be of help, have a nice Sunday!
Changing your animals to let animals = [a1, a2, a3], I get [SortGroups.Animal(Name: "A", Group: "cats"), SortGroups.Animal(Name: "B", Group: "dogs"), SortGroups.Animal(Name: "C", Group: "cats")], seems your code does not sorting the array correctly.
Still wrong. Try adding let a4 = Animal(Name: "D", Group: "dogs") and let animals = [a1, a2, a3, a4]. Two element lexicographical order cannot be achieved with $0.Group <= $1.Group && $0.Name < $1.Name.
My output [SortGroups.Animal(Name: "A", Group: "cats"), SortGroups.Animal(Name: "B", Group: "dogs"), SortGroups.Animal(Name: "C", Group: "cats"), SortGroups.Animal(Name: "D", Group: "dogs")] (Xcode 9.4.1).
|

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.