读取数组中的字符串并将其转换为 Smalltalk 中的数组

Read string in an array and convert it to array in Smalltalk

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

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

这是我目前所做的:

语法:

| 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'))

我想要达到的目标:

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

您想将第一个 collection 的每个元素(行字符串)转换为基于原始元素的不同元素(单词数组)。这就是 collect: 消息 Collections.

的目的
arrValues := fileValues collect: 
    [:each | | inner |
    inner := OrderedCollection new.
    stream := ReadStream on: each.
    [(word := stream upTo: Core.Character space) isEmpty]
        whileFalse: [inner addLast: word].
    inner asArray "<-- this is the answer value of this block"]

请注意,根据您的 Smalltalk 方言,String 中可能存在某种拆分方法。

我冒昧地做了更多 "smalltalk" 方式,因为 @JayK 向您展示了更通用的方式(它不处理 'Ho chi min' 的问题)。

我所有的例子都使用 Smalltalk/X-jv。我尽量顺其自然,这样的问题怎么想。

首先想到的是 "just" 通过 space 拆分它(一个 space 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' 城市中有一个 space。

有什么办法可以解决吗?在你的场景中有。让我们使用 two spaces 而不是 one:

来拆分它
| 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 文件,但带有 ;。 (没有人说将来你会有两个 spaces 来分割它 - 所以你需要有一个分割器来定义字符串的结尾 - 这可能是 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.