Как отсортировать данные JSON в массиве в Swift 4 - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть такой массив JSON

 var json = NSArray()  // array with json objects

 //print json >>
   json = (
                {
                Name = "Alen";
                Score = 500;
            },
                {
                Name = "John";
                Score = 0;
            },
                {
                Name = "Mark";
                Score = 2000;
            },
                {
                Name = "Steve";
                Score = 300;
            },
                {
                Name = "Ricky";
                Score = 900;
            }
        )

, и я могу получить доступ к его объектам как

(json[0] as! NSDictionary).object(forKey: "Name")
(json[0] as! NSDictionary).object(forKey: "Score")

Я хочу отсортировать этот массив JSON в соответствии с оценками.

Я нашел ответы типа

let sortedArray = json.sorted(by: { $0.0 < $1.0 })

, что дает ошибку

Значение типа 'Any' не имеет члена '0'

Тогда япробовал это

 let sortedArray = (json as! NSDictionary).sorted {(aDic, bDic)  -> Bool in
                return aDic.key < bDic.key
            }

выдает ошибку

Двоичный оператор '<' нельзя применить к двум 'любым' операндам </p>

Можете ли вы указатьмне отсортировать массив по счету в swift 4?

Ответы [ 4 ]

0 голосов
/ 25 апреля 2018

Это очень хороший пример того, почему вам настоятельно не рекомендуется использовать NSArray и NSDictionary в Swift.

Оба типа коллекции не предоставляют информацию о типе, поэтому все рассматривается как Any. Большая часть общего универсального API стандартной библиотеки Swift не может использоваться с Any, поэтому вы не сможете воспользоваться мощными универсальными функциями, если не добавите много уродливых приведений типов.

Если все значения String, объявите ваш массив как

var json = [[String:String]]()

Затем вы можете отсортировать массив с помощью

let sortedArray = json.sorted { $0["Score"]! < $1["Score"]! }

Наиболее рекомендуемое решение - декодировать JSON непосредственно в пользовательскую структуру

struct Player : Decodable {
    let name : String
    let score : String

    private enum CodingKeys : String, CodingKey { case name = "Name", score = "Score" }
}

Затем вы избавляетесь от всех типов приведения и можете сортировать по имени свойства

var players = [Player]()

let jsonString = """
[{"Name" : "Alen", "Score" : "500"},
{"Name" : "John", "Score" : "0"},
{"Name" : "Mark", "Score" : "2000"},
{"Name" : "Steve", "Score" : "300"},
{"Name" : "Ricky", "Score" : "900"}]
"""

let data = Data(jsonString.utf8)
do {
    players = try JSONDecoder().decode([Player].self, from: data)
    let sortedPlayers = players.sorted{ $0.score.compare($1.score, options: .numeric) == .orderedAscending }
    print(sortedPlayers)
} catch { print(error) }

Edit:

Для загрузки JSON используйте асинхронный способ (URLSession)

Никогда не загружайте данные с удаленного URL с синхронным Data(contentsOf.

var players = [Player]()

let jsonUrl = URL(string: "url.json")! 
let task = URLSession.shared.dataTask(with : url) { [unowned self] (data, _, error) in 
    if let error = error { print(error); return }
    do {
        players = try JSONDecoder().decode([Player].self, from: data!).sorted{ $0.score < $1.score }
        DispatchQueue.main.async { // reload the table view if necessary
            self.tableView.reloadData()
        }
    } catch { print(error) }
}
task.resume()
0 голосов
/ 25 апреля 2018

Если массив содержит словарь, вы можете использовать этот код для сортировки:

let sortedArray = json.sort { $0["Score"] as! Int < $1["Score"] as! Int }
print(sortedArray)

и если вы используете класс бобов, вы можете использовать свойства точки (.) Для сортировки:

let sortedArray = json.sort { $0.Score < $1.Score }
print(sortedArray)
0 голосов
/ 25 апреля 2018

Я делал что-то подобное до

Сначала я создал два массива словаря

var jsonArray =  [(name:String, score:String)]()
var sortedscoreArray:[(name: String, score: String)] = []

и при получении данных JSON вы можете создать для цикла

for I in 0..< jsonData.count{
  Let jsonInfo = jsonData[i]
  jsonArray.append((name: jsonInfo[“Name”].string!, score: jsonInfo[“Score"].string!))
}

и после заполнения массива json передайте его в sortedArray

sortedscoreArray =  jsonArray.sorted(by: { $0.score < $1.score })
0 голосов
/ 25 апреля 2018

После анализа вашего json вы можете отсортировать массив оценок следующим образом

var scoreArray = ["500", "0", "2000", "300", "900"]
array.sort { $0.compare($1, options: .numeric) == .orderedAscending }
...