【问题标题】:Why doesn't my array start with the first item that is mapped to it? Swift为什么我的数组不是从映射到它的第一项开始?迅速
【发布时间】:2017-10-13 06:56:34
【问题描述】:

我正在编写一个应用程序,以使用 Swift 显示和浏览一系列问题和答案。我目前有一个问题字典和相关答案,然后我使用 .map 创建一个“抽认卡”对象数组(每个都包含一个问题和相关答案)。

当我从数组中访问这些对象时,由于某种原因,返回的第 0 项似乎是我字典中的第二项而不是第一项(例如“问题 2”)。有人可以解释这是为什么吗?这是创建数据数组并提供将项目返回到相关视图控制器的方法的类:

    import Foundation

class Deck {
    // Create constant to hold the deck of cards
    private var cards: [Flashcard]
    var bookmark: Int // Remembers which card we are on


    init() {
        let cardData = ["Question 1" : "Answer 1",
                        "Question 2" : "Answer 2",
                        "Question 3" : "Answer 3"]

        cards = cardData.map { Flashcard(question: $0, answer: $1) }
        bookmark = 0 // Start with bookmark on first item in deck
    }

    // Getter method to return current card
    public func getCurrentCard() -> Flashcard {
        print("Bookmark set to \(bookmark)")
        return cards[bookmark]
    }

    // Getter method to return the next card in the deck
    public func getNextCard() -> Flashcard {
        bookmark += 1
        print("Bookmark set to \(bookmark)")
        return cards[bookmark]
    }

    // Getter method to return previous card in deck
    public func getLastCard() -> Flashcard {
        bookmark -= 1
        print("Bookmark set to \(bookmark)")
        return cards[bookmark]
    }
}

然后这是我请求显示对象的视图控制器:

import UIKit

class QuestionController: UIViewController {

  // Outlet for the 'question' label
    @IBOutlet weak var questionTextView: UITextView!

    // Outlet for the next button
    @IBAction func nextQuestion(_ sender: UIButton) {
        flashcard = deck.getNextCard()
        questionTextView.text = flashcard?.question

    }

    // Outlet for last button
    @IBAction func lastQuestion(_ sender: UIButton) {
        flashcard = deck.getLastCard()
        questionTextView.text = flashcard?.question
    }



    // variable to hold current flashcard
    var flashcard: Flashcard?
    let deck = Deck() // Holds deck of data

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        flashcard = deck.getCurrentCard()
        questionTextView.text = flashcard?.question

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }



// Prepare flashcard item to be passed to the answer controller before segue
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let answerController = segue.destination as? AnswerController {
            answerController.flashcard = flashcard
        }
    }

}

当我运行应用程序时,显示的第一个问题是“问题 2”,而我期望它是“问题 1”...?

【问题讨论】:

标签: arrays swift dictionary


【解决方案1】:

问题在于 Dictionary 中的键值对的顺序是未指定的 - 它完全依赖于实现,并且不能保证与键值对的顺序相同对出现在您用于创建字典的字典文字中。

在您的情况下,一个简单的解决方案是使用 DictionaryLiteral,而不是字典,它保持键值对的顺序:

init() {
    let cardData: DictionaryLiteral = ["Question 1" : "Answer 1",
                                       "Question 2" : "Answer 2",
                                       "Question 3" : "Answer 3"]

    cards = cardData.map { Flashcard(question: $0, answer: $1) }
    bookmark = 0 // Start with bookmark on first item in deck
}

这是因为under the hoodDictionaryLiteral 只不过是一个键值元组数组。因此,您会注意到它的行为与 Dictionary 非常不同,并且保持键值对的顺序:

  • 它有一个从零开始的 Int 索引,您可以使用它来下标
  • 不要求密钥为Hashable
  • 它允许重复键
  • 密钥查找在线性(非恒定)时间内进行

因此,在您将键值对打包到您的实际数据结构中之前,它的主要用途实际上只是一点临时语法糖(允许使用字典文字)——这正是我们在这里使用它的方式。

【讨论】:

  • 感谢 Hamish,我想知道这是否与此有关,但我想它可能会在每次运行应用程序时随机从不同的对象开始,而它总是从第二项开始。
  • @laurie Happy help :) 值得注意的是,即使在 same 程序的执行之间,Dictionary 中的键值对的顺序也不值得依赖– 因为Hashable 协议不保证同一实例在不同执行过程中返回的哈希值是稳定的(这在文档中特别说明)。
  • 您好@Hamish,您认为自定义模型数组会更好吗?顺便说一句,我终于看到了DictionaryLiteral 的有用用法,感谢您的回答。
  • @AhmadF 自定义模型数组正是 OP 在这种情况下所做的([Flashcard])——DictionaryLiteral 在这里的使用实际上仅用于语法糖,因此 OP 不会不必为每个元素写出一个重复“Flashcard(question: ... , answer: ...)”的数组文字。相反,我们只需要说明问题和答案字符串对。
猜你喜欢
  • 2020-10-14
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 2016-11-28
  • 1970-01-01
  • 2020-04-07
  • 2021-09-26
相关资源
最近更新 更多