Problème de devoirs. Je dois parcourir un éventail de dictionnaires pour obtenir le gpa le plus élevé et imprimer le prénom et le nom de l'étudiant. J'ai des problèmes pour accéder au champ gpa des entrées de dictionnaire.
for index in students {
myGPA = Double(index["gpa"])
if myGPA > highestGPA {
highestGPA = myGPA
}
}
Les résultats attendus seraient qu'il itère dans le tableau de dictionnaires et obtient le gpa le plus élevé. Le résultat réel est une erreur de compilation "L'opérateur binaire '>' ne peut pas être appliqué aux opérandes de type (, , String) et Double. Donc, il semble qu'il obtient la chaîne "gpa" plutôt que la valeur de gpa
EDIT: J'ai aussi essayé le code suivant pour obtenir la valeur dans le champ "gpa" et le convertir en double.
// Task 6
var highestGPA = 0.0
var students : [[String:Any]] =
[["firstName": "John", "lastName": "Wilson", "gpa": 2.4],
["firstName": "Nancy", "lastName": "Smith", "gpa": 3.5],
["firstName": "Michael", "lastName": "Liu", "gpa": 3.1]]
for index in students {
if let val = (_,_,"gpa":key) {
highestGPA = val
}
}
J'obtiens l'erreur de compilation: erreur: impossible d'appeler l'initialiseur pour le type 'Double' avec une liste d'arguments de type '(Any?)' myGPA = Double (index ["gpa"])
3 Réponses :
Parce que vous avez marqué les valeurs dans votre dictionnaire comme Any , lorsque vous l'utilisez, vous devez le réduire comme? Double . Le code ci-dessous résout votre problème.
var highestGpa = 0.0
var highestPerformingStudent = students[0]
for student in students {
if let gpa = student["gpa"] as? Double {
if (gpa > highestGpa) {
highestGpa = gpa
highestPerformingStudent = student
}
}
}
print(highestPerformingStudent)
// prints ["firstName": "Nancy", "lastName": "Smith", "gpa": 3.5]
Vous devez éviter autant que possible les lancers de force. Si un dictionnaire ne contient pas de clé gpa , il plantera toute l'application.
+1 à ce que @EmilioPelaez a dit, forcer le déballage est rarement un bon conseil, veuillez ne pas recommander des trucs comme ça aux débutants.
C'est ce que l'enseignant de la classe nous a recommandé de faire.
@RossSatchell c'est bon à entendre - faites attention aux downcasting forcés comme mentionné par d'autres. J'ai édité la réponse pour démontrer les meilleures pratiques.
Vous pouvez utiliser la fonction Array max pour déterminer l'élève ayant le GPA le plus élevé.
let student = students.max { $0["gpa"] as? Double ?? 0 < $1["gpa"] as? Double ?? 0 }
print(student?["firstName"]) // Nancy
print(student?["gpa"]) // 3.5
oups, aurait dû d'abord tester sur le terrain de jeu. Merci!
Comme @Alexander l'a suggéré dans les commentaires, il serait préférable de définir une struct pour contenir votre nom d'élève et vos données gpa. Ensuite, vous aurez des membres fortement typés et vous n'aurez pas à convertir Any en String et Double . Les structures fournissent automatiquement un initialiseur qui prend chacun des membres. Cela vous évite de faire une faute de frappe lors de l'initialisation de votre tableau de données Student .
Création de votre struct CustomStringConvertible et implémentation de var description vous permet de formater la sortie de la struct joliment.
Vous pouvez ensuite utiliser max (by :) pour trouver l ' étudiant avec le plus grand gpa en passant une fermeture qui définit comment comparer deux enregistrements Student .
let students = [
("John", "Wilson", 2.4),
("Nancy", "Smith", 3.5),
("Michael", "Liu", 3.1)
].map(Student.init)
Sortie: p >
Nancy Smith (3.5) Nancy Smith 3.5
Autre façon d'initialiser les données Student :
Comme @LeoDabus l'a suggéré, vous pouvez utiliser un tableau de tuples et map () pour initialiser votre tableau élèves comme ceci:
struct Student: CustomStringConvertible {
var firstName: String
var lastName: String
var gpa: Double
var description: String { return "\(firstName) \(lastName) (\(gpa))" }
}
let students: [Student] = [
Student(firstName: "John", lastName: "Wilson", gpa: 2.4),
Student(firstName: "Nancy", lastName: "Smith", gpa: 3.5),
Student(firstName: "Michael", lastName: "Liu", gpa: 3.1)
]
if let student = students.max(by: { $0.gpa < $1.gpa }) {
// Print the student information
print(student)
// Print the student's name
print("\(student.firstName) \(student.lastName)")
// Print the highest gpa
print(student.gpa)
}
Cela a l'avantage d'éliminer l'encombrement visuel et économiser la saisie au prix de ne pas afficher explicitement les champs en cours d'initialisation.
Devrait créer des structures pour stocker les personnes, au lieu de tableaux. De cette façon, vous pouvez avoir des membres fortement typés (gpa sera un
Doublequi n'a pas besoin de la constanteas! Doubleforce cast) et n'aura pas à utiliser de chaînes pour rechercher des membres (et si vous faites une faute de frappe?)si laissez myGPA = index ["gpa"] comme? Double {