无法将文本文件读入所需的数组格式

Posted

技术标签:

【中文标题】无法将文本文件读入所需的数组格式【英文标题】:Trouble reading in text file into needed array format 【发布时间】:2019-01-03 03:59:02 【问题描述】:

我正在尝试压缩我正在处理的一个应用程序,该应用程序涉及一个包含大量UIViewControllersUITableViews 的大目录。

我的计划是重写应用程序,该应用程序将使用可重复使用的UIViewControllerUITableView,它将在运行时/运行后根据需要从 txt 文件中加载数据。 txt 文件将在运行时/之后读取,而不必事先构建所有 swift 文件。

目前,每次我对项目进行更改时,我的应用程序都需要几分钟来构建/编译。因此,我希望通过根据需要读取和解析 txt 文件,我将能够在几秒钟内构建应用程序。

下面是我尝试使用下面提供的示例文本文件 (candyTextFile.txt) 来读取和生成必要的“糖果”数组。 请查看课程中的注释行 MasterViewController,以获取错误消息和我尝试将糖果数组输出为的代码。

注意,我已将文本文件中的行数缩短为三行。我的最终应用程序将包含许多类似的文本文件,每个文件都扩展数百行。

我对 Swift 还比较陌生,所以如果我在这里遗漏了一些简单的东西,或者我使用/不使用适当的术语,我深表歉意。

我相信 CandySearch 一词仅来自项目名称(请参阅 here )。我不确定为什么它会在candies 数组中输出。另外,我现在确实看到我当前的myArray 已建立为一个类。如何把它变成一个数组?

这是我MasterViewController.swift中的相关代码,

class MasterViewController: UIViewController, UITableViewDataSource, UITableViewDelegate 
    var candies = [myArray]()
    var evenIndicies = [String]()
    var oddIndicies = [String]()

    override func viewDidLoad() 
        super.viewDidLoad()

        setUpArray()
    

    private func setUpArray() 
        if let filepath = Bundle.main.path(forResource: "candyTextFile", ofType: "txt") 
            do 
                // let contents = try String(contentsOfFile: "candyTextFile", encoding: String.Encoding.utf8)
                let contents = try String(contentsOfFile: filepath)
                let lines_separatedBy_n : [String] = contents.components(separatedBy: "\n")
                let string = lines_separatedBy_n.map  String($0) .joined(separator: ", ")
                print("string: \(string)")
                let lines_separatedBy_comma : [String] = string.components(separatedBy: ", ")
                print("lines_separatedBy_comma: \(lines_separatedBy_comma)")

                for (index, element) in lines_separatedBy_comma.enumerated() 
                    if index % 2 == 0 
                        evenIndicies.append(element)
                        print("evenIndicies: \(evenIndicies)")

                     else 
                        oddIndicies.append(element)
                        print("oddIndicies: \(oddIndicies)")
                    
                
                evenIndicies.remove(at: evenIndicies.count - 1) // the -1 removes the nil element, "", in the array. For some reason, there is a fourth element, "", in the evenIndicies array. Therefore, I remove it by subtracting one index so I get the three indexes. My in project txt file is four lines long where the fourth line is empty. I think this is why it is showing up "" for the fourth index.
                print("evenIndicies outside for-loop: \(evenIndicies)")
                print("oddIndicies outside for-loop: \(oddIndicies)")
                candies = [myArray(category: evenIndicies, name: oddIndicies)]  // 

                print("candies: \(candies)") 
           // This prints as the following:
           // candies: [CandySearch.myArray]

           // HOWEVER, I am trying to get it to print as: 
           // [CandySearch.myArray(category: "Chocolate", name: "Chocolate Bar"), CandySearch.myArray(category: "Chocolate", name: "Chocolate Cookie"), CandySearch.myArray(category: "Hard", name: "Lollipop")]




             catch let error as NSError 
                print(error.localizedDescription)
            
        
    


class myArray 
    let category: [String]
    let name: [String]
    init(category: [String], name: [String]) 
        self.category = category
        self.name = name
    

在我的文本文件中,candyTextFile.txt,我有

Chocolate, Chocolate Bar
Chocolate, Chocolate Cookie
Hard, Lollipop

【问题讨论】:

请出示Candy类的代码。您将candies 定义为包含myArray 类型的数组,然后尝试使用Candy 类型的单个实例填充它,因此出现错误消息。 哦,哇,这对我来说是个大错误。请查看更新的代码!谢谢大家的帮助。 对不起,如果我在之前的评论中不清楚。问题仍未解决。 您能否更新您的答案以删除/解释您评论的打印声明中的 CandySearch 是什么?无论如何,您仍然使用myArray 的单个实例填充candies,这是一个类而不是数组。您预期的打印输出似乎有点偏离标准。除了 myArray 实例的属性之外,categoryname 属性没有任何关系。我的意思是,例如每个数组的元素并没有像您预期的打印输出那样配对。 好的,我在原始帖子的中间附近添加了一段关于我认为CandySearch 的来源以及如何将myArray 转换为一个数组来保存属性category 和@ 987654348@ 【参考方案1】:

假设您想要做的是从文本文件中获取信息并最终得到一系列糖果产品,我将对此进行尝试。目前你的myArray 类看起来有点像科学怪人的东西。它包含该类的单个实例内的两个单独数组中的所有类别和名称。然后将它放入一个名为candies 的数组中。除非我误解了您的要求,否则这一切看起来都是死胡同。 (也许我是。)但假设我至少对了一半......

你想要一个糖果数组,所以让我们创建一个新类来容纳一个糖果。

class Candy 
    let category: String!
    let name: String!

    init(category: String, name: String) 
        self.category = category
        self.name = name
    

这类似于您已经拥有的,但是当您实例化Candy 的实例时,它将保存单个糖果的详细信息。注意类名按照约定以大写字母开头。

你想得到一个糖果数组,所以让我们改变你的candies数组的定义。

var candies: [Candy] = []

剩下的就是更改您的for in 循环以在每个循环中提取一个糖果的数据(类别和名称),创建一个新的Candy 实例并在将其添加到candies 之前填充它。

for (index, element) in lines_separatedBy_comma.enumerated() 
   var newCategory = ""
   var newName = ""
   if index % 2 == 0 
      newCategory = element
    else 
      newName = element
   
   let newCandy = Candy(category: newCategory, name: newName)
   candies.append(newCandy)

您的代码中没有任何检查可以处理文本文件中的任何错误/错误格式,所以我假设您绝对确定它是由没有松散端的数据对组成的,等等。我看到你出于某种原因删除了evenIndices 的最后一个元素。我不知道为什么,所以我没有处理。

现在您的 candies 数组应该包含一堆 Candy 对象,因此要将它们列出到控制台,您可以执行以下操作。

for candy in candies 
   print("category: \(String(describing: candy.category)), name: \(String(describing: candy.name))")

如果我仍然错过标记,请告诉我。

编辑 ************************************************ ********** 编辑

我看了你链接的 RW 教程。

本教程使用struct 作为Candy 元素,而您(和我)使用了一个类。我猜你还在学习 Swift 的值和引用类型,所以不会进一步混淆这里的水。在这种情况下,可以说struct 可能会更好。 print 也以不同的方式处理它们,并且似乎能够在结构内部查找值,而除非您显式提取属性(如在我的 for in print 语句中,它只是为您提供我们所见的类列表。

我还对逻辑进行了排序(它很丑,你不应该这样做),所以你至少可以看到它确实有效(在时尚之后)。整个setupArray方法:

private func setupArray() 
     if let filepath = Bundle.main.path(forResource: "candyTextFile", ofType: "txt") 
         do 
             let contents = try String(contentsOfFile: filepath)
             let lines_separatedBy_n : [String] = contents.components(separatedBy: "\n")
             let string = lines_separatedBy_n.map  String($0) .joined(separator: ", ")
             var lines_separatedBy_comma : [String] = string.components(separatedBy: ", ")

             // I've put this in to remove the last bit of the file that was causing the count to be one too high.
             // I'm guessing that's why you had something similar previously?
             lines_separatedBy_comma.removeLast()

             for (index, element) in lines_separatedBy_comma.enumerated() 
                 if index % 2 == 0 
                     let newCategory = element
                     let newName = lines_separatedBy_comma[index + 1]
                     let newCandy = Candy(category: newCategory, name: newName)
                     candies.append(newCandy)
                 
             
             for candy in candies 
                 print("category: \(candy.category!), name: \(candy.name!)")
             
             print("\ncandies: \(candies)")
          catch let error as NSError 
             print(error.localizedDescription)
         
     
 

当我使用时:

class Candy 
    let category: String!
    let name: String!

    init(category: String, name: String) 
        self.category = category
        self.name = name
    

输出是:

category: Chocolate, name: Chocolate Bar
category: Chocolate, name: Chocolate Cookie
category: Hard, name: Lollipop

candies: [FileTest.Candy, FileTest.Candy, FileTest.Candy]

当我使用时:(从打印语句中移除强制展开后)

struct Candy 
    let category : String
    let name : String

输出是:

category: Chocolate, name: Chocolate Bar
category: Chocolate, name: Chocolate Cookie
category: Hard, name: Lollipop

candies: [FileTest.Candy(category: "Chocolate", name: "Chocolate Bar"), FileTest.Candy(category: "Chocolate", name: "Chocolate Cookie"), FileTest.Candy(category: "Hard", name: "Lollipop")]

您是否看到您的原始代码将所有内容都放在一个 myArray 中,但上面的代码(以及在 RW 网站上)创建了单独的 Candy 元素并将它们全部存储到 candies 中?这是方法的根本区别。

【讨论】:

当我调用打印语句print("candies: \(candies)") 时,您的解决方案输出的内容与我的相同,但您的解决方案打印出newCandy: [CandySearch.Candy, CandySearch.Candy, CandySearch.Candy, CandySearch.Candy, CandySearch.Candy, CandySearch.Candy, CandySearch.Candy]。这不是我想要的。我正在尝试将打印语句打印为[CandySearch.myArray(category: "Chocolate", name: "Chocolate Bar"), CandySearch.myArray(category: "Chocolate", name: "Chocolate Cookie"), CandySearch.myArray(category: "Hard", name: "Lollipop")]。抱歉让您感到困惑,但我认为 我们走在正确的轨道上。我正在尝试在本教程 (raywenderlich.com/…) 中生成糖果数组内容。很抱歉早些时候把它漏掉了。如果您在链接教程中调用print("candies: \(candies)"),它会输出candies: Candy(category:"Chocolate", name:"Chocolate Bar"), Candy(category:"Chocolate", name:"Chocolate Chip"), Candy(category:"Chocolate", name:"Dark Chocolate"), Candy(category:"Hard", name:"Lollipop"),以此类推到最后。我试图模仿这种行为,但通过读取文本文件。 您的回答对于调试此问题仍然非常有帮助,因此感谢您抽出宝贵时间。对于任何混淆,我再次道歉。 注意,我相信您的newCandy 等同于我在此答案的顶部评论中的candies 请看一下我原始答案的“大”编辑。

以上是关于无法将文本文件读入所需的数组格式的主要内容,如果未能解决你的问题,请参考以下文章

从文本文件中将数据读入 numpy 数组

将本地文本文件读入 JavaScript 数组 [重复]

Python将文本文件读入2D阵列并访问数据

c++ 将文本文件中的 3 列读入 2D 数组或 3 个单独的数组

将文本文件读入结构化 2D numpy 数组

node.js:将文本文件读入数组。 (每一行都是数组中的一个项目。)