首页 > 解决方案 > 读取数组中的字符串并将其转换为 Smalltalk 中的数组

问题描述

我正在尝试读取包含单词集的文本文件并将它们转换为集合。我首先做的是,每当有回车时,我通过将它们分开来对单词进行分组。我成功地将它存储在一个数组中。我想做的下一件事是读取字符串数组的内容,并通过将它们分成数组内的数组来再次对单词进行分组。可能吗?希望你能帮助我。谢谢!

我尝试循环当前集合并放置一些条件来修剪空格并将它们放入数组内的新集合中,但它不起作用。

这是我到目前为止所做的:

句法:

| fileName fileRead values |
fileName := 'fruitVendor.txt'.
fileRead := fileName asFilename readStream.
fileValues := OrderedCollection new.
arrValues := OrderedCollection new.
[(string := fileRead upTo: Core.Character cr) isEmpty]
    whileFalse: [fileValues addLast: string].
param := fileValues asArray.
param do: 
        [:ea |
        stream := ReadStream on: ea.
        [(arrString := stream upTo: Core.Character space) isEmpty]
            whileFalse: [arrValues addLast: arrString].]

这是文件的内容:

fruitVendor.txt

China     Beijing     Apple  //cr
Hawaii    Honolulu    Pineapple   //cr
Japan     Tokyo       Banana //cr
Vietnam   Ho chi min  Pear

输出应该是:

#(#('China' 'Beijing' 'Apple')#('Hawaii' 'Honolulu' ''Pineapple)#('Japan' 'Tokyo' 'Banana')#('Vietnam' 'Ho chi min' 'Pear'))

我想要达到的目标:

将数组内部的字符串存储到数组本身内部的一个新数组中,更像是一个字节数组。

标签: arraysoopobjectsmalltalk

解决方案


我冒昧地以更“smalltalk”的方式进行操作,因为@JayK 向您展示了更通用的方式(它不处理 的问题'Ho chi min')。

我所有的例子都在使用Smalltalk/X-jv. 我会尝试以自然的方式来做,人们会如何看待这样的问题。

首先想到的是通过空格(一个空格Character space)“只是”分割它。三是这样一个方便的选择器#splitBy:,称为#splitByAll:第二个示例。

所以我们尝试一下:

| readFileStream citiesCollection |

readFileStream := 'C:\t\so\smalltalk\fruitVendor_space.txt' asFilename readStream.
citiesCollection := OrderedCollection new.

readFileStream linesDo: [ :eachLine |
    | cities |
    cities := (eachLine splitBy: Character space) select: [ :eachCity | eachCity notEmpty ].   
    citiesCollection add: cities asArray
].

citiesCollection inspect

结果可能不是你所期望的,因为最后一个 Array 是:

#('Vietnam' 'Ho' 'chi' 'min' 'Pear')

这是因为你在字符串'Ho chi min'城市有一个空间。

有没有办法处理它?在你的场景中有。让我们使用两个空格而不是一个空格来拆分它:

| readFileStream citiesCollection spitCollection |

readFileStream := 'C:\t\so\smalltalk\fruitVendor_space.txt' asFilename readStream.
citiesCollection := OrderedCollection new.
spitCollection := OrderedCollection new.
2 timesRepeat: [ spitCollection add: (Character space) ]. "/ adding two spaces

readFileStream linesDo: [ :eachLine |
    | cities |
    cities := (eachLine splitByAll: spitCollection) select: [ :eachCity | eachCity notEmpty ].
    cities := cities copy collect: [ :eachCity | eachCity withoutSpaces ].
    citiesCollection add: cities asArray
].

citiesCollection inspect.

现在我们得到了'Ho chi min'城市字符串的正确结果。

#('Vietnam' 'Ho chi min' 'Pear')

话虽如此,我认为最可取的方式(在现实生活中)是通过使用某种拆分器(例如$;;字符)-类似csv文件但带有;. (没有人说将来你会有两个空格来分割它——所以你需要一个分割器来定义字符串的结尾——这可能是 csv 出现的主要原因)。

源文件将是:

China;    Beijing;    Apple;
Hawaii;   Honolulu;   Pineapple;
Japan;    Tokyo;      Banana;
Vietnam;  Ho chi min; Pear;

然后代码看起来类似于上面的第一个代码:

| readFileStream citiesCollection |

readFileStream := 'C:\t\so\smalltalk\fruitVendor.txt' asFilename readStream.
citiesCollection := OrderedCollection new.

readFileStream linesDo: [ :eachLine |
    | cities |
    cities := (eachLine splitBy: $;) collect: [ :eachCity | eachCity withoutSpaces ].
    citiesCollection add: cities asArray
].

citiesCollection inspect.

推荐阅读