好的,所以我在过去的几个月里一直在学习如何在业余时间进行编程,而我现在正试图了解如何仅使用来自.json文件的数据已被过滤。
例如,假设我有一个.json文件,格式如下:
{
"id" : "1",
"question": "Earth is a:",
"answers": [
"Planet",
"Meteor",
"Star",
"Asteroid"
],
"category": "astronomy"
},
{
"id":"2",
"question":"Which country won the 2006 Soccer World Cup?",
"answers":[
"Italy",
"Germany",
"France",
"Brazil"
],
"category": "sport"
}
我的问题
假设我将所有数据都放在一个.json文件中,如何只加载 符合特定条件的数据,或加载所有数据,然后只选择符合特定标准的数据?显然,最终结果必须是只将过滤后的数据混洗并显示给用户。
道歉,如果这是显而易见的,但作为一个新手,我只是没有知识/经验来找到比我下面描述的多文件方法更好的方法。我确实试着寻找答案,但是找不到一个似乎适用于我的场景的答案。如果有,我已经错过了,请转发给我。
某些背景
目前我使用以下代码加载我的数据:
func LoadAllQuestionsAndAnswers()
{
let path = NSBundle.mainBundle().pathForResource("content", ofType: "json")
let jsonData : NSData = NSData(contentsOfFile: path!)!
allEntries = (try! NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers)) as! NSArray
//println(allEntries)
}
显然,上面的从.json文件加载所有数据。加载此数据后,我将使用以下代码重新调整所有问题:
if #available(iOS 9.0, *) {
shuffledQuestions = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(allEntries as [AnyObject])
nextQuestion++
LoadQuestion(nextQuestion)
// Fallback on earlier versions
}else{
let randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
LoadQuestionPreiOS9(randomNumber)
}
一旦洗牌,我就会使用以下代码向用户提出问题:
func LoadQuestion(index : Int)
{
let entry : NSDictionary = shuffledQuestions[index] as! NSDictionary
let question : NSString = entry.objectForKey("question") as! NSString
let arr : NSMutableArray = entry.objectForKey("answers") as! NSMutableArray
let QID : NSString = entry.objectForKey("id") as! NSString
if let a = arr.objectAtIndex(0) as? String {
self.answertext = a
}
//println(question)
//println(arr)
labelQuestion.text = question as String
labelQID.text = QID as String
所以,我想做的是让用户选择他们想要回答的问题类别。现在显然我可以通过为每个类别使用单独的.json文件并使用if else
语句来完成此操作。例如,我可以有一个astronomy.json文件,一个sport.json文件等,然后使用如下代码:
func LoadChosenCategory()
{
let defaults = NSUserDefaults.standardUserDefaults()
if (chosencategory == 1)
{
let path = NSBundle.mainBundle().pathForResource("astronomy", ofType: "json")
let jsonData : NSData = NSData(contentsOfFile: path!)!
allEntries = (try! NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers)) as! NSArray
//println(allEntries)
}else{
if (lastchosenchallenge == 2)
{
let path = NSBundle.mainBundle().pathForResource("sport", ofType: "json")
let jsonData : NSData = NSData(contentsOfFile: path!)!
allEntries = (try! NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers)) as! NSArray
//println(allEntries)
}else{
依此类推。
但我相信必须有更有效的方法来做到这一点,我想学习如何,因此这个问题。
好的,所以我试图按照Russell的回答中的建议,但是不能让它发挥作用。它运行良好,但似乎并没有真正过滤数据。
以下是我尝试和实施罗素答案所做的工作。
首先我创建了几个整数变量:
var categoryfilter : Int! = 0
var lastcategoryfilter : Int! = 0
然后我创建了一些函数来保存和加载NSUserDefaults的值:
func LoadLastCategoryFilter()
{
let defaults = NSUserDefaults.standardUserDefaults()
lastcategoryfilter = defaults.integerForKey("ChosenCategory")
}
func SaveLastCategoryFilter()
{
lastcategoryfilter = categoryfilter
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setInteger(lastcategoryfilter, forKey: "ChosenCategory")
}
然后我使用按钮,以便用户可以设置变量的值并切换到游戏'屏幕:
@IBAction func buttonAstronomyCategory(sender: AnyObject) {
categoryfilter = 1
SaveLastCategoryFilter()
ResetGameFromMainMenu()
switchToMainGameScreen()
}
@IBAction fund buttonSportCategory(sender: AnyObject) {
categoryfilter = 2
SaveLastCategoryFilter()
ResetGameFromMainMenu()
switchToMainGameScreen()
}
等等每个类别。
在游戏界面中,我有一个加载lastcategoryfilter值的函数,然后按如下方式加载.json数据:
func LoadAllQuestionsAndAnswers()
{
let path = NSBundle.mainBundle().pathForResource("content", ofType: "json")
let jsonData : NSData = NSData(contentsOfFile: path!)!
allEntries = (try! NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers)) as! NSArray
if (lastcategoryfilter == 1)
{
let filteredEntries = allEntries.filter() {$0.category == "astronomy"}
print(filteredEntries)
}else{
if (lastcategoryfilter == 2)
{
let filteredEntries = allEntries.filter() {$0.category == "sport"}
print(filteredEntries)
}else{
if (lastcategoryfilter == 3)
{
let filteredEntries = allEntries.filter() {$0.category == "History"}
print(filteredEntries)
}else{
if (lastcategoryfilter == 4)
{
let filteredEntries = allEntries.filter() {$0.category == "Politics"}
print(filteredEntries)
}else{
if (lastcategoryfilter == 5)
{
let filteredEntries = allEntries.filter() {$0.category == "Technology"}
print(filteredEntries)
}}}}}}
然后我使用与前面描述相同的功能来混淆/随机化问题并将其呈现给用户。
代码一切正常(即没有错误),但我的数据没有被过滤。
我不知道我哪里出错了,但我确定这只是一个愚蠢的新手错误!有什么建议吗?
答案 0 :(得分:1)
过滤您的阵列很容易。这是一个相当人为的例子,它没有解决JSON或随机问题,但确实显示了过滤部分。显然,在你的例子中,你不会像我这里那样创建命名数组,但这个例子运行得很好。
struct QuestionStruct
{
var id : Int
var question : String
var category : String
var answer : String
}
class ViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
var questions : [QuestionStruct] = []
questions.append(QuestionStruct(id: 1, question:"question 1", category:"English", answer:"answer 1"))
questions.append(QuestionStruct(id: 2, question:"question 2", category:"Physics", answer:"answer 2"))
questions.append(QuestionStruct(id: 3, question:"question 3", category:"Physics", answer:"answer 3"))
questions.append(QuestionStruct(id: 4, question:"question 4", category:"Maths", answer:"answer 4"))
questions.append(QuestionStruct(id: 5, question:"question 5", category:"English", answer:"answer 5"))
let filteredQuestionsPhysics = questions.filter() { $0.category == "Physics" }
let filteredQuestionsEnglish = questions.filter() { $0.category == "English" }
let filteredQuestionsMaths = questions.filter() { $0.category == "Maths" }
}
}
更具体地说,在您的示例中,您可能希望修改LoadAllQuestionsAndAnswers
以返回特定的问题列表而不是所有内容。此后,您可以像以前一样随机化它
func LoadAllQuestionsAndAnswers()
{
let path = NSBundle.mainBundle().pathForResource("content", ofType: "json")
let jsonData : NSData = NSData(contentsOfFile: path!)!
allEntries = (try! NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers)) as! NSArray
//println(allEntries)
let filteredEntries = allEntries.filter() {$0.category == categoryFilter}
println(filteredEntries)
}
答案 1 :(得分:1)
确定Monomeeth
- 我们可以采取一些措施来提高代码的可读性和可维护性。首先,我们可以删除所有嵌套的if
语句,并使所有内容更加通用。
虽然你会有一系列按钮 - 你可以让他们都使用相同的方法,因为你每次都做同样的事情。如果将每个按钮的tag
值设置为索引值,我们将知道哪个按钮将我们带到了该方法。如果您将categories
存储在数组中,那么我们就不需要对Astronomy
进行硬编码,我们只需使用categories[0]
以下是您需要的代码的关键部分
首先获得所有定义
class ViewController: UIViewController
{
var categoryFilter : Int = 0
var lastcategoryfilter : Int = 0
let categories : [String] = ["Astronomy", "Sport", "History", "Politics", "Technology"] // if you have LOTS of these, you might want to load in a file and parse it ...
var questions : [QuestionStruct] = [] // QuestionStruct is whatever structure you need to store the questions
var filteredEntries : [QuestionStruct] = []
然后您需要一种方法来处理按下按钮,所有类别选择按钮都附加到
@IBAction func cmdSelectCategory(sender: AnyObject)
{
// ALL of the buttons for select category are linked to this one method
// the buttons have a tag value set to act as index
categoryFilter = sender.tag
generateFilteredQuestionSet()
}
然后您需要根据categoryFilter
func generateFilteredQuestionSet()
{
filteredEntries = questions.filter() { $0.category == categories[categoryFilter]}
print(filteredEntries)
}
祝你好运!