如果Pharo Smalltalk中的陈述(无回报)为flatten list

问题描述:

我试图列出(30)列表(30)。 我有这样的:如果Pharo Smalltalk中的陈述(无回报)为flatten list

#(#(a a a) nil nil #(b) #(c) #(d) nil nil nil #(e e) nil #(f f) nil #(g) 
    #(h) nil nil nil #(i i) nil nil nil #(j) nil nil nil nil nil 
    #(k) #(l l l) 

而且我希望做一个程序,轮流到这只是一个像这样的列表:

#(a a a b c d e e f f g hi i j k l l l) 

我的代码是这样的:

ToList: lista 
    | retorno y z | 
    retorno := Array new: 30. 
    y := 1. 
    (1 to: lista size) 
     do: [ :i | 
      z := 0. 
      (lista at: i) isNil 
      ifFalse: 
      (1 to: (lista at: i) size do: [ :j | retorno at: (y + z) put: ((lista at: i) at: j) 
       y:= y+1. 
       z:= z +1.] 
      )]. 
     ^retorno 

我想if语句存在一些问题,因为没有回报。我不知道该怎么做,因为它的工作方式没有y:= y+1.,但它保留了一些零空格。

请帮帮我!

+0

'flatCollect'可以在单一方法调用中处理此问题 – Alexander

+2

您应该为变量提供更多描述性名称,以便代码更易于理解。我可以是outerIndex,y可以是outputIndex,j可以是innerIndex,z ......好吧,不管你对z的意图是什么。 – JayK

+1

除了亚历山大的提示,如果你应该自己编写一种flatCollect:考虑不要按索引访问集合元素,而是直接访问。而不是'1:列表大小:[:index | “做些什么”(list at:index)]'简单地写'list do:[:each | “与每个人做某事]'。对于输出,您可以使用OrderedCollection而不是Array来简单地使用'add:'来追加元素。你也可以看看Squeak/Pharo所有藏品都能理解的信息:“收集:”。 – JayK

有你的代码中有两处语法错误:

  1. ifTrue:ifFalse:等参数时,块与块在Smalltalk括在方括号,括号没有表情。在你的情况,你应该写

    (lista at: i) isNil 
        ifFalse: 
        [1 to: (lista at: i    "<- [ not (" 
    

    ,并密切与

     z:= z +1.] 
        ]].        "<- ]] not)]." 
    
  2. 有一个点在长行的末尾丢失:

    .... put: ((lista at: i) at: j)   "<- dot missing" 
         y:= y+1. 
         z:= z +1. 
    

修复这些后两个问题你应该能够运行代码,看看它是否按预期工作(或者如果不是,则调试)。但这是另一回事......


附录

也有可疑的东西在这里。

在Smalltalk中,我们使用单引号分隔文字字符串('Hello world')和文字字符前的美元符号,如$a

另外,我们有字面数组,它由其他文字组成,并包含在#()之间,如#('a' $a)

现在,在您的代码中,您已经编写了诸如#(a a a)之类的表达式,这些表达式不符合我们刚才看到的格式。那么这是什么意思?更确切地说,Smalltalk编译器如何解释这个符号?答案是,它会假设你的意思是:

#(#a #a #a) 

即的Symbols数组,你不想写那么多#秒。因此,在您的练习中,您应该考虑是否确实需要字符#($a $a $a),字符串#('a' 'a' 'a')或符号#(#a #a #a)

其他字符串也是如此。例如,#(abc de)会被编译为#(#abC#de) ...

...嗯...

但是且慢。如果是这样,那么为什么#(#(a a a) nil)不会编译为#(#(a a a) #nil)?那么,因为编译器与niltruefalse ......异常!

还要注意,在Smalltalk的一些方言编译器将interprete #((a a a))作为#(#(a a a))所以你不必键入多英镑符号...

总结。如果您选择在字面阵列中节省一些磅数,请保持一致并写入#((a a a))而不是#(#(a a a))。否则completeley显式并写#(#(#a #a #a))

你可以把它写成:

flattenArray: anArray 
    | ws | 

    ws = WriteStream on: (Array new). 
    anArray do: [:subArr| : 
        subArr notNil ifTrue: [ 
         subArr do: [ :el | ws nextPut: el ]]]. 
    ^ws contents. 

有2分总论,这是很少需要通过索引来访问集合元素,如果你正在做它,停,并认为,如果有更优雅的方法可用。第二个WriteStreams在您想要收集一系列结果时非常方便。