Scala: Find and update one element in a list
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I am trying to find an elegant way to do:
val l = List(1,2,3)
val (item, idx) = l.zipWithIndex.find(predicate)
val updatedItem = updating(item)
l.update(idx, updatedItem)
Can I do all in one operation ? Find the item, if it exist replace with updated value and keep it in place.
I could do:
l.map{ i =>
if (predicate(i)) {
updating(i)
} else {
i
}
}
but that's pretty ugly.
The other complexity is the fact that I want to update only the first element which match predicate
.
Edit: Attempt:
implicit class UpdateList[A](l: List[A]) {
def filterMap(p: A => Boolean)(update: A => A): List[A] = {
l.map(a => if (p(a)) update(a) else a)
}
def updateFirst(p: A => Boolean)(update: A => A): List[A] = {
val found = l.zipWithIndex.find { case (item, _) => p(item) }
found match {
case Some((item, idx)) => l.updated(idx, update(item))
case None => l
}
}
}
scala functional-programming scalaz
add a comment |
I am trying to find an elegant way to do:
val l = List(1,2,3)
val (item, idx) = l.zipWithIndex.find(predicate)
val updatedItem = updating(item)
l.update(idx, updatedItem)
Can I do all in one operation ? Find the item, if it exist replace with updated value and keep it in place.
I could do:
l.map{ i =>
if (predicate(i)) {
updating(i)
} else {
i
}
}
but that's pretty ugly.
The other complexity is the fact that I want to update only the first element which match predicate
.
Edit: Attempt:
implicit class UpdateList[A](l: List[A]) {
def filterMap(p: A => Boolean)(update: A => A): List[A] = {
l.map(a => if (p(a)) update(a) else a)
}
def updateFirst(p: A => Boolean)(update: A => A): List[A] = {
val found = l.zipWithIndex.find { case (item, _) => p(item) }
found match {
case Some((item, idx)) => l.updated(idx, update(item))
case None => l
}
}
}
scala functional-programming scalaz
I just realized the issue haha. I only want to do it on the first item found.
– Wonay
Jan 3 at 2:50
1
Given that I can only think in having a mutable variable to track if an update already was made and do the map withif (!alreadyUpdated && predicate(i))
- you can encapsulate everything in a method to don't expose the mutable variable. For a completely immutable solution, I would use afoldLeft
in which you accumulate the new List (backwards) and the flag ofalreadyUpdated
, after the fold you may extract the List and then reverse it - however it will have complexity 2O(N) (two iterations) and may be too complex. Not sure if there is a better way, that is why I dont answer
– Luis Miguel Mejía Suárez
Jan 3 at 2:58
then I feel than myupdateFirst
method is the best so far ?
– Wonay
Jan 3 at 3:04
1
Wonay, IMHO no. The intention is very clear that is a point! - but it does a lot of iterations (O(3N) in case the first element is near to the end) and creates one extra intermediate collection. If you're sure the collections will be small and the first item will be near the beginning it may not be so bad. Aki, I don't believe that is a good idea, because he/she needs the element too, thus it will need to call apply with that index again which will result in another iteration - but will make the intention more clear!, which is a point! Other idea would be to use Vector instead of List.
– Luis Miguel Mejía Suárez
Jan 3 at 3:12
How would that work with a vector ?
– Wonay
Jan 3 at 4:16
add a comment |
I am trying to find an elegant way to do:
val l = List(1,2,3)
val (item, idx) = l.zipWithIndex.find(predicate)
val updatedItem = updating(item)
l.update(idx, updatedItem)
Can I do all in one operation ? Find the item, if it exist replace with updated value and keep it in place.
I could do:
l.map{ i =>
if (predicate(i)) {
updating(i)
} else {
i
}
}
but that's pretty ugly.
The other complexity is the fact that I want to update only the first element which match predicate
.
Edit: Attempt:
implicit class UpdateList[A](l: List[A]) {
def filterMap(p: A => Boolean)(update: A => A): List[A] = {
l.map(a => if (p(a)) update(a) else a)
}
def updateFirst(p: A => Boolean)(update: A => A): List[A] = {
val found = l.zipWithIndex.find { case (item, _) => p(item) }
found match {
case Some((item, idx)) => l.updated(idx, update(item))
case None => l
}
}
}
scala functional-programming scalaz
I am trying to find an elegant way to do:
val l = List(1,2,3)
val (item, idx) = l.zipWithIndex.find(predicate)
val updatedItem = updating(item)
l.update(idx, updatedItem)
Can I do all in one operation ? Find the item, if it exist replace with updated value and keep it in place.
I could do:
l.map{ i =>
if (predicate(i)) {
updating(i)
} else {
i
}
}
but that's pretty ugly.
The other complexity is the fact that I want to update only the first element which match predicate
.
Edit: Attempt:
implicit class UpdateList[A](l: List[A]) {
def filterMap(p: A => Boolean)(update: A => A): List[A] = {
l.map(a => if (p(a)) update(a) else a)
}
def updateFirst(p: A => Boolean)(update: A => A): List[A] = {
val found = l.zipWithIndex.find { case (item, _) => p(item) }
found match {
case Some((item, idx)) => l.updated(idx, update(item))
case None => l
}
}
}
scala functional-programming scalaz
scala functional-programming scalaz
edited Jan 3 at 2:54
Wonay
asked Jan 3 at 2:34
WonayWonay
399213
399213
I just realized the issue haha. I only want to do it on the first item found.
– Wonay
Jan 3 at 2:50
1
Given that I can only think in having a mutable variable to track if an update already was made and do the map withif (!alreadyUpdated && predicate(i))
- you can encapsulate everything in a method to don't expose the mutable variable. For a completely immutable solution, I would use afoldLeft
in which you accumulate the new List (backwards) and the flag ofalreadyUpdated
, after the fold you may extract the List and then reverse it - however it will have complexity 2O(N) (two iterations) and may be too complex. Not sure if there is a better way, that is why I dont answer
– Luis Miguel Mejía Suárez
Jan 3 at 2:58
then I feel than myupdateFirst
method is the best so far ?
– Wonay
Jan 3 at 3:04
1
Wonay, IMHO no. The intention is very clear that is a point! - but it does a lot of iterations (O(3N) in case the first element is near to the end) and creates one extra intermediate collection. If you're sure the collections will be small and the first item will be near the beginning it may not be so bad. Aki, I don't believe that is a good idea, because he/she needs the element too, thus it will need to call apply with that index again which will result in another iteration - but will make the intention more clear!, which is a point! Other idea would be to use Vector instead of List.
– Luis Miguel Mejía Suárez
Jan 3 at 3:12
How would that work with a vector ?
– Wonay
Jan 3 at 4:16
add a comment |
I just realized the issue haha. I only want to do it on the first item found.
– Wonay
Jan 3 at 2:50
1
Given that I can only think in having a mutable variable to track if an update already was made and do the map withif (!alreadyUpdated && predicate(i))
- you can encapsulate everything in a method to don't expose the mutable variable. For a completely immutable solution, I would use afoldLeft
in which you accumulate the new List (backwards) and the flag ofalreadyUpdated
, after the fold you may extract the List and then reverse it - however it will have complexity 2O(N) (two iterations) and may be too complex. Not sure if there is a better way, that is why I dont answer
– Luis Miguel Mejía Suárez
Jan 3 at 2:58
then I feel than myupdateFirst
method is the best so far ?
– Wonay
Jan 3 at 3:04
1
Wonay, IMHO no. The intention is very clear that is a point! - but it does a lot of iterations (O(3N) in case the first element is near to the end) and creates one extra intermediate collection. If you're sure the collections will be small and the first item will be near the beginning it may not be so bad. Aki, I don't believe that is a good idea, because he/she needs the element too, thus it will need to call apply with that index again which will result in another iteration - but will make the intention more clear!, which is a point! Other idea would be to use Vector instead of List.
– Luis Miguel Mejía Suárez
Jan 3 at 3:12
How would that work with a vector ?
– Wonay
Jan 3 at 4:16
I just realized the issue haha. I only want to do it on the first item found.
– Wonay
Jan 3 at 2:50
I just realized the issue haha. I only want to do it on the first item found.
– Wonay
Jan 3 at 2:50
1
1
Given that I can only think in having a mutable variable to track if an update already was made and do the map with
if (!alreadyUpdated && predicate(i))
- you can encapsulate everything in a method to don't expose the mutable variable. For a completely immutable solution, I would use a foldLeft
in which you accumulate the new List (backwards) and the flag of alreadyUpdated
, after the fold you may extract the List and then reverse it - however it will have complexity 2O(N) (two iterations) and may be too complex. Not sure if there is a better way, that is why I dont answer– Luis Miguel Mejía Suárez
Jan 3 at 2:58
Given that I can only think in having a mutable variable to track if an update already was made and do the map with
if (!alreadyUpdated && predicate(i))
- you can encapsulate everything in a method to don't expose the mutable variable. For a completely immutable solution, I would use a foldLeft
in which you accumulate the new List (backwards) and the flag of alreadyUpdated
, after the fold you may extract the List and then reverse it - however it will have complexity 2O(N) (two iterations) and may be too complex. Not sure if there is a better way, that is why I dont answer– Luis Miguel Mejía Suárez
Jan 3 at 2:58
then I feel than my
updateFirst
method is the best so far ?– Wonay
Jan 3 at 3:04
then I feel than my
updateFirst
method is the best so far ?– Wonay
Jan 3 at 3:04
1
1
Wonay, IMHO no. The intention is very clear that is a point! - but it does a lot of iterations (O(3N) in case the first element is near to the end) and creates one extra intermediate collection. If you're sure the collections will be small and the first item will be near the beginning it may not be so bad. Aki, I don't believe that is a good idea, because he/she needs the element too, thus it will need to call apply with that index again which will result in another iteration - but will make the intention more clear!, which is a point! Other idea would be to use Vector instead of List.
– Luis Miguel Mejía Suárez
Jan 3 at 3:12
Wonay, IMHO no. The intention is very clear that is a point! - but it does a lot of iterations (O(3N) in case the first element is near to the end) and creates one extra intermediate collection. If you're sure the collections will be small and the first item will be near the beginning it may not be so bad. Aki, I don't believe that is a good idea, because he/she needs the element too, thus it will need to call apply with that index again which will result in another iteration - but will make the intention more clear!, which is a point! Other idea would be to use Vector instead of List.
– Luis Miguel Mejía Suárez
Jan 3 at 3:12
How would that work with a vector ?
– Wonay
Jan 3 at 4:16
How would that work with a vector ?
– Wonay
Jan 3 at 4:16
add a comment |
2 Answers
2
active
oldest
votes
I don't know any way to make this in one pass of the collection without using a mutable variable. With two passes you can do it using foldLeft
as in:
def updateFirst[A](list:List[A])(predicate:A => Boolean, newValue:A):List[A] = {
list.foldLeft((List.empty[A], predicate))((acc, it) => {acc match {
case (nl,pr) => if (pr(it)) (newValue::nl, _ => false) else (it::nl, pr)
}})._1.reverse
}
The idea is that foldLeft
allows passing additional data through iteration. In this particular implementation I change the predicate to the fixed one that always returns false
. Unfortunately you can't build a List
from the head in an efficient way so this requires another pass for reverse
.
I believe it is obvious how to do it using a combination of map
and var
Note: performance of the List.map
is the same as of a single pass over the list only because internally the standard library is mutable. Particularly the cons class ::
is declared as
final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {
so tl
is actually a var
and this is exploited by the map
implementation to build a list from the head in an efficient way. The field is private[scala]
so you can't use the same trick from outside of the standard library. Unfortunately I don't see any other API call that allows to use this feature to reduce the complexity of your problem to a single pass.
add a comment |
You can avoid .zipWithIndex()
by using .indexWhere()
.
To improve complexity, use Vector
so that l(idx)
becomes effectively constant time.
val l = Vector(1,2,3)
val idx = l.indexWhere(predicate)
val updatedItem = updating(l(idx))
l.updated(idx, updatedItem)
Reason for using scala.collection.immutable.Vector
rather than List
:
Scala's List is a linked list, which means data are access in O(n) time. Scala's Vector is indexed, meaning data can be read from any point in effectively constant time.
You may also consider mutable collections if you're modifying just one element in a very large collection.
https://docs.scala-lang.org/overviews/collections/performance-characteristics.html
1
That's not better than the author's code becausel(idx)
isO(N)
– SergGr
Jan 3 at 3:14
Would you mind editing your solution with Vector ? Would any of the code change or just the performances ?
– Wonay
Jan 3 at 4:17
1
edited. code is exactly the same
– Leighton Ritchie
Jan 3 at 4:43
1
Wonay as Leighton already said the code will no change, but its performance will be sightly better. However be aware thatVectors
are not as great as one expects
– Luis Miguel Mejía Suárez
Jan 3 at 12:29
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54015611%2fscala-find-and-update-one-element-in-a-list%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I don't know any way to make this in one pass of the collection without using a mutable variable. With two passes you can do it using foldLeft
as in:
def updateFirst[A](list:List[A])(predicate:A => Boolean, newValue:A):List[A] = {
list.foldLeft((List.empty[A], predicate))((acc, it) => {acc match {
case (nl,pr) => if (pr(it)) (newValue::nl, _ => false) else (it::nl, pr)
}})._1.reverse
}
The idea is that foldLeft
allows passing additional data through iteration. In this particular implementation I change the predicate to the fixed one that always returns false
. Unfortunately you can't build a List
from the head in an efficient way so this requires another pass for reverse
.
I believe it is obvious how to do it using a combination of map
and var
Note: performance of the List.map
is the same as of a single pass over the list only because internally the standard library is mutable. Particularly the cons class ::
is declared as
final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {
so tl
is actually a var
and this is exploited by the map
implementation to build a list from the head in an efficient way. The field is private[scala]
so you can't use the same trick from outside of the standard library. Unfortunately I don't see any other API call that allows to use this feature to reduce the complexity of your problem to a single pass.
add a comment |
I don't know any way to make this in one pass of the collection without using a mutable variable. With two passes you can do it using foldLeft
as in:
def updateFirst[A](list:List[A])(predicate:A => Boolean, newValue:A):List[A] = {
list.foldLeft((List.empty[A], predicate))((acc, it) => {acc match {
case (nl,pr) => if (pr(it)) (newValue::nl, _ => false) else (it::nl, pr)
}})._1.reverse
}
The idea is that foldLeft
allows passing additional data through iteration. In this particular implementation I change the predicate to the fixed one that always returns false
. Unfortunately you can't build a List
from the head in an efficient way so this requires another pass for reverse
.
I believe it is obvious how to do it using a combination of map
and var
Note: performance of the List.map
is the same as of a single pass over the list only because internally the standard library is mutable. Particularly the cons class ::
is declared as
final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {
so tl
is actually a var
and this is exploited by the map
implementation to build a list from the head in an efficient way. The field is private[scala]
so you can't use the same trick from outside of the standard library. Unfortunately I don't see any other API call that allows to use this feature to reduce the complexity of your problem to a single pass.
add a comment |
I don't know any way to make this in one pass of the collection without using a mutable variable. With two passes you can do it using foldLeft
as in:
def updateFirst[A](list:List[A])(predicate:A => Boolean, newValue:A):List[A] = {
list.foldLeft((List.empty[A], predicate))((acc, it) => {acc match {
case (nl,pr) => if (pr(it)) (newValue::nl, _ => false) else (it::nl, pr)
}})._1.reverse
}
The idea is that foldLeft
allows passing additional data through iteration. In this particular implementation I change the predicate to the fixed one that always returns false
. Unfortunately you can't build a List
from the head in an efficient way so this requires another pass for reverse
.
I believe it is obvious how to do it using a combination of map
and var
Note: performance of the List.map
is the same as of a single pass over the list only because internally the standard library is mutable. Particularly the cons class ::
is declared as
final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {
so tl
is actually a var
and this is exploited by the map
implementation to build a list from the head in an efficient way. The field is private[scala]
so you can't use the same trick from outside of the standard library. Unfortunately I don't see any other API call that allows to use this feature to reduce the complexity of your problem to a single pass.
I don't know any way to make this in one pass of the collection without using a mutable variable. With two passes you can do it using foldLeft
as in:
def updateFirst[A](list:List[A])(predicate:A => Boolean, newValue:A):List[A] = {
list.foldLeft((List.empty[A], predicate))((acc, it) => {acc match {
case (nl,pr) => if (pr(it)) (newValue::nl, _ => false) else (it::nl, pr)
}})._1.reverse
}
The idea is that foldLeft
allows passing additional data through iteration. In this particular implementation I change the predicate to the fixed one that always returns false
. Unfortunately you can't build a List
from the head in an efficient way so this requires another pass for reverse
.
I believe it is obvious how to do it using a combination of map
and var
Note: performance of the List.map
is the same as of a single pass over the list only because internally the standard library is mutable. Particularly the cons class ::
is declared as
final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {
so tl
is actually a var
and this is exploited by the map
implementation to build a list from the head in an efficient way. The field is private[scala]
so you can't use the same trick from outside of the standard library. Unfortunately I don't see any other API call that allows to use this feature to reduce the complexity of your problem to a single pass.
edited Jan 3 at 3:26
answered Jan 3 at 3:18
SergGrSergGr
21.4k22243
21.4k22243
add a comment |
add a comment |
You can avoid .zipWithIndex()
by using .indexWhere()
.
To improve complexity, use Vector
so that l(idx)
becomes effectively constant time.
val l = Vector(1,2,3)
val idx = l.indexWhere(predicate)
val updatedItem = updating(l(idx))
l.updated(idx, updatedItem)
Reason for using scala.collection.immutable.Vector
rather than List
:
Scala's List is a linked list, which means data are access in O(n) time. Scala's Vector is indexed, meaning data can be read from any point in effectively constant time.
You may also consider mutable collections if you're modifying just one element in a very large collection.
https://docs.scala-lang.org/overviews/collections/performance-characteristics.html
1
That's not better than the author's code becausel(idx)
isO(N)
– SergGr
Jan 3 at 3:14
Would you mind editing your solution with Vector ? Would any of the code change or just the performances ?
– Wonay
Jan 3 at 4:17
1
edited. code is exactly the same
– Leighton Ritchie
Jan 3 at 4:43
1
Wonay as Leighton already said the code will no change, but its performance will be sightly better. However be aware thatVectors
are not as great as one expects
– Luis Miguel Mejía Suárez
Jan 3 at 12:29
add a comment |
You can avoid .zipWithIndex()
by using .indexWhere()
.
To improve complexity, use Vector
so that l(idx)
becomes effectively constant time.
val l = Vector(1,2,3)
val idx = l.indexWhere(predicate)
val updatedItem = updating(l(idx))
l.updated(idx, updatedItem)
Reason for using scala.collection.immutable.Vector
rather than List
:
Scala's List is a linked list, which means data are access in O(n) time. Scala's Vector is indexed, meaning data can be read from any point in effectively constant time.
You may also consider mutable collections if you're modifying just one element in a very large collection.
https://docs.scala-lang.org/overviews/collections/performance-characteristics.html
1
That's not better than the author's code becausel(idx)
isO(N)
– SergGr
Jan 3 at 3:14
Would you mind editing your solution with Vector ? Would any of the code change or just the performances ?
– Wonay
Jan 3 at 4:17
1
edited. code is exactly the same
– Leighton Ritchie
Jan 3 at 4:43
1
Wonay as Leighton already said the code will no change, but its performance will be sightly better. However be aware thatVectors
are not as great as one expects
– Luis Miguel Mejía Suárez
Jan 3 at 12:29
add a comment |
You can avoid .zipWithIndex()
by using .indexWhere()
.
To improve complexity, use Vector
so that l(idx)
becomes effectively constant time.
val l = Vector(1,2,3)
val idx = l.indexWhere(predicate)
val updatedItem = updating(l(idx))
l.updated(idx, updatedItem)
Reason for using scala.collection.immutable.Vector
rather than List
:
Scala's List is a linked list, which means data are access in O(n) time. Scala's Vector is indexed, meaning data can be read from any point in effectively constant time.
You may also consider mutable collections if you're modifying just one element in a very large collection.
https://docs.scala-lang.org/overviews/collections/performance-characteristics.html
You can avoid .zipWithIndex()
by using .indexWhere()
.
To improve complexity, use Vector
so that l(idx)
becomes effectively constant time.
val l = Vector(1,2,3)
val idx = l.indexWhere(predicate)
val updatedItem = updating(l(idx))
l.updated(idx, updatedItem)
Reason for using scala.collection.immutable.Vector
rather than List
:
Scala's List is a linked list, which means data are access in O(n) time. Scala's Vector is indexed, meaning data can be read from any point in effectively constant time.
You may also consider mutable collections if you're modifying just one element in a very large collection.
https://docs.scala-lang.org/overviews/collections/performance-characteristics.html
edited Jan 3 at 4:42
answered Jan 3 at 3:13
Leighton RitchieLeighton Ritchie
556
556
1
That's not better than the author's code becausel(idx)
isO(N)
– SergGr
Jan 3 at 3:14
Would you mind editing your solution with Vector ? Would any of the code change or just the performances ?
– Wonay
Jan 3 at 4:17
1
edited. code is exactly the same
– Leighton Ritchie
Jan 3 at 4:43
1
Wonay as Leighton already said the code will no change, but its performance will be sightly better. However be aware thatVectors
are not as great as one expects
– Luis Miguel Mejía Suárez
Jan 3 at 12:29
add a comment |
1
That's not better than the author's code becausel(idx)
isO(N)
– SergGr
Jan 3 at 3:14
Would you mind editing your solution with Vector ? Would any of the code change or just the performances ?
– Wonay
Jan 3 at 4:17
1
edited. code is exactly the same
– Leighton Ritchie
Jan 3 at 4:43
1
Wonay as Leighton already said the code will no change, but its performance will be sightly better. However be aware thatVectors
are not as great as one expects
– Luis Miguel Mejía Suárez
Jan 3 at 12:29
1
1
That's not better than the author's code because
l(idx)
is O(N)
– SergGr
Jan 3 at 3:14
That's not better than the author's code because
l(idx)
is O(N)
– SergGr
Jan 3 at 3:14
Would you mind editing your solution with Vector ? Would any of the code change or just the performances ?
– Wonay
Jan 3 at 4:17
Would you mind editing your solution with Vector ? Would any of the code change or just the performances ?
– Wonay
Jan 3 at 4:17
1
1
edited. code is exactly the same
– Leighton Ritchie
Jan 3 at 4:43
edited. code is exactly the same
– Leighton Ritchie
Jan 3 at 4:43
1
1
Wonay as Leighton already said the code will no change, but its performance will be sightly better. However be aware that
Vectors
are not as great as one expects– Luis Miguel Mejía Suárez
Jan 3 at 12:29
Wonay as Leighton already said the code will no change, but its performance will be sightly better. However be aware that
Vectors
are not as great as one expects– Luis Miguel Mejía Suárez
Jan 3 at 12:29
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54015611%2fscala-find-and-update-one-element-in-a-list%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I just realized the issue haha. I only want to do it on the first item found.
– Wonay
Jan 3 at 2:50
1
Given that I can only think in having a mutable variable to track if an update already was made and do the map with
if (!alreadyUpdated && predicate(i))
- you can encapsulate everything in a method to don't expose the mutable variable. For a completely immutable solution, I would use afoldLeft
in which you accumulate the new List (backwards) and the flag ofalreadyUpdated
, after the fold you may extract the List and then reverse it - however it will have complexity 2O(N) (two iterations) and may be too complex. Not sure if there is a better way, that is why I dont answer– Luis Miguel Mejía Suárez
Jan 3 at 2:58
then I feel than my
updateFirst
method is the best so far ?– Wonay
Jan 3 at 3:04
1
Wonay, IMHO no. The intention is very clear that is a point! - but it does a lot of iterations (O(3N) in case the first element is near to the end) and creates one extra intermediate collection. If you're sure the collections will be small and the first item will be near the beginning it may not be so bad. Aki, I don't believe that is a good idea, because he/she needs the element too, thus it will need to call apply with that index again which will result in another iteration - but will make the intention more clear!, which is a point! Other idea would be to use Vector instead of List.
– Luis Miguel Mejía Suárez
Jan 3 at 3:12
How would that work with a vector ?
– Wonay
Jan 3 at 4:16