I have a sequence in Ceylon and I want to make a new sequence with one of the elements replaced with something else according an index:
[String*] strings = ["zero", "one", "two"];
value index = 1;
value newElement= "uno";
[String*]? newStrings = ???; // should be ["zero", "uno", "two"]
In Scala, this is called update
.
There are several ways to solve this problem, and I do like the solution by Quintesse above, using Array
. That is, perhaps, what I would do in practice. However, there is one possibly-important downside of the Array
solution: it allocates memory twice.
So let me just suggest a couple of different options, for the sake of completeness:
This works, but is a bit verbose:
[String*] strings = ["zero", "one", "two"];
value index = 1;
value newElement= "uno";
[String*] newStrings =
strings.take(index)
.chain(strings.skip(index+1).follow(newElement))
.sequence();
Note that here we are using the lazy stream operations take()
, skip()
, chain()
and follow()
to create a lazy stream of elements, and then the sequence()
operation to take a copy into a new sequence. It allocates just once, in the call to sequence()
.
patch()
This also works:
[String*] strings = ["zero", "one", "two"];
value index = 1;
value newElement= "uno";
[String*] newStrings =
strings.patch([newElement], index, 1)
.sequence();
Note that if it's good enough to get back an immutable List
, you could drop the call to sequence()
, resulting in:
[String*] strings = ["zero", "one", "two"];
value index = 1;
value newElement= "uno";
[String*] newStrings =
strings.patch([newElement], index, 1);
And in this case there's no allocation at all (except for one trivial instance of List.Patch
).
See the docs for List.patch()
.