更新不可变序列

时间:2016-01-18 22:11:31

标签: ceylon

我在Ceylon中有一个序列,我想根据索引创建一个新的序列,其中一个元素被其他元素替换:

[String*] strings = ["zero", "one", "two"];
value index = 1;
value newElement= "uno";
[String*]? newStrings = ???; // should be ["zero", "uno", "two"]

在Scala中,这称为update

3 个答案:

答案 0 :(得分:5)

有几种方法可以解决这个问题,而我 就像上面的Quintesse解决方案一样,使用Array。那也许就是我在实践中会做的事情。但是,Array解决方案有一个可能重要的缺点:它分配内存两次

因此,为了完整起见,我只想提出几个不同的选择:

使用流操作

这有效,但有点冗长:

[String*] strings = ["zero", "one", "two"];
value index = 1;
value newElement= "uno";
[String*] newStrings = 
    strings.take(index)
           .chain(strings.skip(index+1).follow(newElement))
           .sequence();

请注意,我们在这里使用延迟流操作take()skip()chain()follow()来创建一个懒惰的元素流,然后{{1操作将副本复制到新序列中。它在sequence()的调用中仅分配一次。

使用sequence()

这也有效:

patch()

请注意,如果能够取回不可变的[String*] strings = ["zero", "one", "two"]; value index = 1; value newElement= "uno"; [String*] newStrings = strings.patch([newElement], index, 1) .sequence(); ,则可以将调用放到List,从而导致:

sequence()

在这种情况下,根本没有分配(除了一个简单的[String*] strings = ["zero", "one", "two"]; value index = 1; value newElement= "uno"; [String*] newStrings = strings.patch([newElement], index, 1); 实例)。

请参阅docs for List.patch()

答案 1 :(得分:3)

你可以理解:

[String*] newStrings = [for (i->e in strings.indexed) i==index then newElement else e];

Try online

答案 2 :(得分:3)

另一种方法是将它复制到一个 可变的数组,然后再返回:

[String*] strings = ["zero", "one", "two"];
value index = 1;
value newElement= "uno";

value array = Array(strings);
array.set(index, newElement);

[String*] newStrings = array.sequence();