TransWikia.com

How to sort array with multiple criteria including the value of enum, names and numbers?

Stack Overflow Asked by Ulugbek on December 30, 2021

I want to sort this array that i have named lists, which includs Player with Positions, what i want to achive is if the one value of Player is nill, for example either "position" in PLayer or year,, then it should be the last element of the array, and enum values according descending order and sort it

example: when i print the first element of array, it should print like names: "Teddy", "Joh", "Alex", "Sia", "Adix", "Javi", "Moris", "Yosa", "Leo", "Davi", "Cars".?

can someone help me to build the sorted func works as I want?

Here is my enum are the just priorities.

enum Position {
  case goalKeeper
  case defender
  case midfield
  case forward 
}

this is my Player struct

struct Player {
  var name: String
  var backNumber: Int?
  var position: Position?
}

and this is my list of players

let list = [
  Player(name: "Abbie", backNumber: nil, position: .defender),
  Player(name: "Tom", backNumber: 99, position: .goalKeeper),
  Player(name: "Carlos", backNumber: 88, position: nil),
  Player(name: "Javier", backNumber: 32, position: .midfield),
  Player(name: "Adam", backNumber: 32, position: .midfield),
  Player(name: "Luis", backNumber: 16, position: .forward),
  Player(name: "John", backNumber: 4, position: .defender),
  Player(name: "Morike", backNumber: 10, position: .forward),
  Player(name: "Silva", backNumber: 24, position: .midfield),
  Player(name: "Yoshida", backNumber: 10, position: .forward),
  Player(name: "David", backNumber: 8, position: nil)
]

and I want to sort it according the positions of the players in descending order
expected output will be like

print("n(["Tom", "John", "Abbie", "Silva", "Adam", "Javier", "Morike", "Yoshida", "Luis", "David", "Carlos"])")

this output above is supposed to achive using sorted method and depending on the positions of the players in descending order, Tom is goalkeeper so in the array it will be the first element, John is midfield ……. Morika and Yoshida is forward and so on,

2 Answers

Easiest solution is update the model where you will add new variable & have calculation for this variable.

struct Player {
  var name: String
  var backNumber: Int?
  var position: Position?

  var sortingVariable : Int? {
      get {
          if (position == nil || backNumber == nil || (name ?? "").isEmpty) {
              return 99 // let's say max limit is 99
          }

          if (position == goalkeeper) {
              return 1
          }
          if (position == defender) {
              return 2
          } // .... & so on...

          return 999 // dummy for nothing...
      }
  }

}

Now sort the array based on sortingVariable

var sortedArray = yourArrayList.sorted({ $0.sortingVariable > $1.sortingVariable })

This way, you can update logic at one place and can be used at any place for sorting.

Hope this is clear.

Answered by Fahim Parkar on December 30, 2021

You can sort your array using the following code

let sorted = list.sorted {
    let firstPositionValue = $0.position?.rawValue ?? Int.max
    let secondPositionValue = $1.position?.rawValue ?? Int.max


    if firstPositionValue == secondPositionValue { // sort by back number or name
        let firstBackNumber = $0.backNumber ?? Int.max
        let secondBackNumber = $1.backNumber ?? Int.max

        if firstBackNumber == secondBackNumber { // sort by name
            return $0.name < $1.name
        }

        return firstBackNumber < secondBackNumber // sort by back number
    }

    return firstPositionValue < secondPositionValue // // sort by position
}

but to be able to sort by the enum the items needs to have a value, the following change will assign each item an increasing int value starting at 1

enum Position: Int {
  case goalKeeper = 1
  case defender
  case midfield
  case forward
}

If you want to you can assign the sort code to a variable

let sortFunction: (Player, Player) -> Bool = {
    let firstPositionValue = $0.position?.rawValue ?? Int.max
    let secondPositionValue = $1.position?.rawValue ?? Int.max
    //... code omitted for brevity 
    let sorted = list.sorted(by: sortFunction)
}

and use it like this to perhaps make the code more readable

let sorted = list.sorted(by: sortFunction)

Yet another option is to make the Player type itself sortable, to do this the type needs to conform to the Comparable protocol

struct Player: Comparable {
    static func < (lhs: Player, rhs: Player) -> Bool {
        let firstPositionValue = lhs.position?.rawValue ?? Int.max
        let secondPositionValue = rhs.position?.rawValue ?? Int.max


        if firstPositionValue == secondPositionValue { // sort by back number or name
            let firstBackNumber = lhs.backNumber ?? Int.max
            let secondBackNumber = rhs.backNumber ?? Int.max

            if firstBackNumber == secondBackNumber { // sort by name
                return lhs.name < rhs.name
            }

            return firstBackNumber < secondBackNumber // sort by back number
        }
        return firstPositionValue < secondPositionValue
    }
    //... rest of code
} 

then we can sort the array in an even simpler way

let sorted = list.sorted()

Answered by Joakim Danielson on December 30, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP