How to Iterate a list of characters and compare different elements
I have a list of strings which I would like to process, so lets say
val List<String?> = listOf("Q", NULL, "W", "E", NULL, "E", "E", "R", "R", "T") [sic]
I want to process this so that I can apply a predicate where there are two matching strings in adjacent positions and return a list of non nullable strings.
The method signature of the extension would then be
fun <T : Any> List<T?>.processList(action: (T) -> T): List<T>
lets say my predicate this time is to add "gotcha" to the first string in a duplicate and remove the second so in this case I would end up with
ListOf("Q", "W", "Egotcha", "E", "Rgotcha", "T")
I can do this in an old school way with a while loop very easily
a messy version being along these lines
val nL : ArrayList<T> = ArrayList<T>()
var indexThis : Int = 0
while ( indexThis < intermediate.size-1 ) {
if (intermediate[indexThis] != intermediate[indexThis + 1]) {
nL.add(intermediate[indexThis]!!)
indexThis += 1 }
else {
nL.add(processList(intermediate[indexThis]!!))
indexThis += 2 }
}
This is a long way from being the finished article but but was my attempt at getting the process clear in my head...
but I'm struggling to get started doing it in a more functional way
so I can see that I might want to do start with
this.filter {a -> a != null}
but then I can't see where I would go as a next step ? Then only method I can think of is forEachIndexed but my attempts at this this seem very convoluted I'm sure I've seen examples of people comparing items in a List in a map ?
and my last train of thought was going along the lines of
.map{b -> b?.run{b ... processList (b)}}
but this seems very wrong
Can anyone point me in the right direction ?
kotlin
add a comment |
I have a list of strings which I would like to process, so lets say
val List<String?> = listOf("Q", NULL, "W", "E", NULL, "E", "E", "R", "R", "T") [sic]
I want to process this so that I can apply a predicate where there are two matching strings in adjacent positions and return a list of non nullable strings.
The method signature of the extension would then be
fun <T : Any> List<T?>.processList(action: (T) -> T): List<T>
lets say my predicate this time is to add "gotcha" to the first string in a duplicate and remove the second so in this case I would end up with
ListOf("Q", "W", "Egotcha", "E", "Rgotcha", "T")
I can do this in an old school way with a while loop very easily
a messy version being along these lines
val nL : ArrayList<T> = ArrayList<T>()
var indexThis : Int = 0
while ( indexThis < intermediate.size-1 ) {
if (intermediate[indexThis] != intermediate[indexThis + 1]) {
nL.add(intermediate[indexThis]!!)
indexThis += 1 }
else {
nL.add(processList(intermediate[indexThis]!!))
indexThis += 2 }
}
This is a long way from being the finished article but but was my attempt at getting the process clear in my head...
but I'm struggling to get started doing it in a more functional way
so I can see that I might want to do start with
this.filter {a -> a != null}
but then I can't see where I would go as a next step ? Then only method I can think of is forEachIndexed but my attempts at this this seem very convoluted I'm sure I've seen examples of people comparing items in a List in a map ?
and my last train of thought was going along the lines of
.map{b -> b?.run{b ... processList (b)}}
but this seems very wrong
Can anyone point me in the right direction ?
kotlin
add a comment |
I have a list of strings which I would like to process, so lets say
val List<String?> = listOf("Q", NULL, "W", "E", NULL, "E", "E", "R", "R", "T") [sic]
I want to process this so that I can apply a predicate where there are two matching strings in adjacent positions and return a list of non nullable strings.
The method signature of the extension would then be
fun <T : Any> List<T?>.processList(action: (T) -> T): List<T>
lets say my predicate this time is to add "gotcha" to the first string in a duplicate and remove the second so in this case I would end up with
ListOf("Q", "W", "Egotcha", "E", "Rgotcha", "T")
I can do this in an old school way with a while loop very easily
a messy version being along these lines
val nL : ArrayList<T> = ArrayList<T>()
var indexThis : Int = 0
while ( indexThis < intermediate.size-1 ) {
if (intermediate[indexThis] != intermediate[indexThis + 1]) {
nL.add(intermediate[indexThis]!!)
indexThis += 1 }
else {
nL.add(processList(intermediate[indexThis]!!))
indexThis += 2 }
}
This is a long way from being the finished article but but was my attempt at getting the process clear in my head...
but I'm struggling to get started doing it in a more functional way
so I can see that I might want to do start with
this.filter {a -> a != null}
but then I can't see where I would go as a next step ? Then only method I can think of is forEachIndexed but my attempts at this this seem very convoluted I'm sure I've seen examples of people comparing items in a List in a map ?
and my last train of thought was going along the lines of
.map{b -> b?.run{b ... processList (b)}}
but this seems very wrong
Can anyone point me in the right direction ?
kotlin
I have a list of strings which I would like to process, so lets say
val List<String?> = listOf("Q", NULL, "W", "E", NULL, "E", "E", "R", "R", "T") [sic]
I want to process this so that I can apply a predicate where there are two matching strings in adjacent positions and return a list of non nullable strings.
The method signature of the extension would then be
fun <T : Any> List<T?>.processList(action: (T) -> T): List<T>
lets say my predicate this time is to add "gotcha" to the first string in a duplicate and remove the second so in this case I would end up with
ListOf("Q", "W", "Egotcha", "E", "Rgotcha", "T")
I can do this in an old school way with a while loop very easily
a messy version being along these lines
val nL : ArrayList<T> = ArrayList<T>()
var indexThis : Int = 0
while ( indexThis < intermediate.size-1 ) {
if (intermediate[indexThis] != intermediate[indexThis + 1]) {
nL.add(intermediate[indexThis]!!)
indexThis += 1 }
else {
nL.add(processList(intermediate[indexThis]!!))
indexThis += 2 }
}
This is a long way from being the finished article but but was my attempt at getting the process clear in my head...
but I'm struggling to get started doing it in a more functional way
so I can see that I might want to do start with
this.filter {a -> a != null}
but then I can't see where I would go as a next step ? Then only method I can think of is forEachIndexed but my attempts at this this seem very convoluted I'm sure I've seen examples of people comparing items in a List in a map ?
and my last train of thought was going along the lines of
.map{b -> b?.run{b ... processList (b)}}
but this seems very wrong
Can anyone point me in the right direction ?
kotlin
kotlin
edited Nov 19 '18 at 12:42
gringogordo
asked Nov 19 '18 at 12:16
gringogordogringogordo
52711031
52711031
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Here is the first pass at this, which is a bit harder functionally because some state must be maintained as you accumulate the result.
fun <T> List<T?>.processList(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: MutableList<T> = mutableListOf(), var previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
// skip this one that was already consumed in the dupe
accum.previousWasDupe = false
} else if (value.size < 2 || value[0] != value[1]) {
accum.resultList.add(value[0])
accum.previousWasDupe = false // already is false, you could delete this line, here for clarity
} else {
accum.resultList.add(action(value[0]))
accum.previousWasDupe = true
}
accum
}.resultList
}
for your test case:
val items = listOf("Q", null, "W", "E", null, "E", "E", "R", "R", "T")
println(items.processList { it + "gotcha" })
// prints "[Q, W, Egotcha, E, Rgotcha, T]"
You could use am immutable accumulator as well (I don't like it being mutable but it will perform better), but there is no point in taking that hit given the state is internal to the function. Whether this performs better as a sequence (as written) or with copies depends on the size of the lists and is hard to say without performance testing.
Notice that I also made sure the items <T>
were Comparable
so that we can be sure that ==
is doing what we expect, otherwise you really don't know you are receiving things that this function would even work upon.
For fun, the immutable version:
fun <T> List<T?>.processListImmutable(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: List<T> = emptyList(), val previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
Accumulator(accum.resultList, false) // could also be: accum.copy(previousWasDupe = false)
} else if (value.size < 2 || value[0] != value[1]) {
Accumulator(accum.resultList + value[0], false)
} else {
Accumulator(accum.resultList + action(value[0]), true)
}
}.resultList
}
An edge case to check with solutions is the input:
val items = listOf("Q", null, "W", "E", null,
"E", "E", "R", "R", "T",
"Z", "Z", "Zgotcha") // <--- this is the trap
which should return:
[Q, W, Egotcha, E, Rgotcha, T, Zgotcha, Zgotcha]
and not:
[Q, W, Egotcha, E, Rgotcha, T, Zgotchagotcha]
Thanks Jayson. Pretty impressive, I hadn't realised it was so involved, I thought I was just being a bit slow... I'm not sure about the edge case tbh, I was thinking about it, it's for an online course and sometimes you only find out the finer points of the requirement when you get the feedback (I'm not sure whether it is recursive so that Z, Z, Zgotcha should become Zgotcha, Zgotcha or Zgotchagotcha ! This is more than enough for me to take the next steps myself though! Many thanks.
– gringogordo
Nov 19 '18 at 16:02
add a comment |
Try next code:
fun List<String?>.processList(action: (String) -> String): List<String> {
var remove = false
val dest = arrayListOf<String>()
return filterNotNullTo(dest).mapIndexedNotNull { index, s ->
if (remove) {
remove = false
null
} else {
if (index + 1 <= dest.lastIndex && s == dest[index + 1]) {
remove = true
action()
} else {
s
}
}
}
}
val l = listOf("Q", null, "W", "E", null, "E", "E", "R", "R", "T")
val result = l.processList {"${it}gotcha"}
This has a bug, in a case such as:val l = listOf("Z", "Z", "Zgotcha")
You cannot use the last modified value as the source of duplicate comparison. It would return["Zgotchagotcha"]
instead of["Zgotcha", "Zgotcha"]
– Jayson Minard
Nov 19 '18 at 14:57
Also you should incorporate the action lambda in the function.
– Jayson Minard
Nov 19 '18 at 14:59
1
Edited my answer including the edge case
– Sergey
Nov 19 '18 at 15:42
Your fix now introduces another edge case.val l = listOf("Z", "Z", "Zgotcha", "Zgotcha")
now does not return["Zgotcha", "Zgotchagotcha"]
as it should.
– Jayson Minard
Nov 19 '18 at 15:45
Thanks. Seems like a fair answer to me but I think of the 2 Jayson's is a better proposition.
– gringogordo
Nov 19 '18 at 15:59
|
show 1 more 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%2f53374448%2fhow-to-iterate-a-list-of-characters-and-compare-different-elements%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
Here is the first pass at this, which is a bit harder functionally because some state must be maintained as you accumulate the result.
fun <T> List<T?>.processList(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: MutableList<T> = mutableListOf(), var previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
// skip this one that was already consumed in the dupe
accum.previousWasDupe = false
} else if (value.size < 2 || value[0] != value[1]) {
accum.resultList.add(value[0])
accum.previousWasDupe = false // already is false, you could delete this line, here for clarity
} else {
accum.resultList.add(action(value[0]))
accum.previousWasDupe = true
}
accum
}.resultList
}
for your test case:
val items = listOf("Q", null, "W", "E", null, "E", "E", "R", "R", "T")
println(items.processList { it + "gotcha" })
// prints "[Q, W, Egotcha, E, Rgotcha, T]"
You could use am immutable accumulator as well (I don't like it being mutable but it will perform better), but there is no point in taking that hit given the state is internal to the function. Whether this performs better as a sequence (as written) or with copies depends on the size of the lists and is hard to say without performance testing.
Notice that I also made sure the items <T>
were Comparable
so that we can be sure that ==
is doing what we expect, otherwise you really don't know you are receiving things that this function would even work upon.
For fun, the immutable version:
fun <T> List<T?>.processListImmutable(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: List<T> = emptyList(), val previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
Accumulator(accum.resultList, false) // could also be: accum.copy(previousWasDupe = false)
} else if (value.size < 2 || value[0] != value[1]) {
Accumulator(accum.resultList + value[0], false)
} else {
Accumulator(accum.resultList + action(value[0]), true)
}
}.resultList
}
An edge case to check with solutions is the input:
val items = listOf("Q", null, "W", "E", null,
"E", "E", "R", "R", "T",
"Z", "Z", "Zgotcha") // <--- this is the trap
which should return:
[Q, W, Egotcha, E, Rgotcha, T, Zgotcha, Zgotcha]
and not:
[Q, W, Egotcha, E, Rgotcha, T, Zgotchagotcha]
Thanks Jayson. Pretty impressive, I hadn't realised it was so involved, I thought I was just being a bit slow... I'm not sure about the edge case tbh, I was thinking about it, it's for an online course and sometimes you only find out the finer points of the requirement when you get the feedback (I'm not sure whether it is recursive so that Z, Z, Zgotcha should become Zgotcha, Zgotcha or Zgotchagotcha ! This is more than enough for me to take the next steps myself though! Many thanks.
– gringogordo
Nov 19 '18 at 16:02
add a comment |
Here is the first pass at this, which is a bit harder functionally because some state must be maintained as you accumulate the result.
fun <T> List<T?>.processList(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: MutableList<T> = mutableListOf(), var previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
// skip this one that was already consumed in the dupe
accum.previousWasDupe = false
} else if (value.size < 2 || value[0] != value[1]) {
accum.resultList.add(value[0])
accum.previousWasDupe = false // already is false, you could delete this line, here for clarity
} else {
accum.resultList.add(action(value[0]))
accum.previousWasDupe = true
}
accum
}.resultList
}
for your test case:
val items = listOf("Q", null, "W", "E", null, "E", "E", "R", "R", "T")
println(items.processList { it + "gotcha" })
// prints "[Q, W, Egotcha, E, Rgotcha, T]"
You could use am immutable accumulator as well (I don't like it being mutable but it will perform better), but there is no point in taking that hit given the state is internal to the function. Whether this performs better as a sequence (as written) or with copies depends on the size of the lists and is hard to say without performance testing.
Notice that I also made sure the items <T>
were Comparable
so that we can be sure that ==
is doing what we expect, otherwise you really don't know you are receiving things that this function would even work upon.
For fun, the immutable version:
fun <T> List<T?>.processListImmutable(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: List<T> = emptyList(), val previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
Accumulator(accum.resultList, false) // could also be: accum.copy(previousWasDupe = false)
} else if (value.size < 2 || value[0] != value[1]) {
Accumulator(accum.resultList + value[0], false)
} else {
Accumulator(accum.resultList + action(value[0]), true)
}
}.resultList
}
An edge case to check with solutions is the input:
val items = listOf("Q", null, "W", "E", null,
"E", "E", "R", "R", "T",
"Z", "Z", "Zgotcha") // <--- this is the trap
which should return:
[Q, W, Egotcha, E, Rgotcha, T, Zgotcha, Zgotcha]
and not:
[Q, W, Egotcha, E, Rgotcha, T, Zgotchagotcha]
Thanks Jayson. Pretty impressive, I hadn't realised it was so involved, I thought I was just being a bit slow... I'm not sure about the edge case tbh, I was thinking about it, it's for an online course and sometimes you only find out the finer points of the requirement when you get the feedback (I'm not sure whether it is recursive so that Z, Z, Zgotcha should become Zgotcha, Zgotcha or Zgotchagotcha ! This is more than enough for me to take the next steps myself though! Many thanks.
– gringogordo
Nov 19 '18 at 16:02
add a comment |
Here is the first pass at this, which is a bit harder functionally because some state must be maintained as you accumulate the result.
fun <T> List<T?>.processList(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: MutableList<T> = mutableListOf(), var previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
// skip this one that was already consumed in the dupe
accum.previousWasDupe = false
} else if (value.size < 2 || value[0] != value[1]) {
accum.resultList.add(value[0])
accum.previousWasDupe = false // already is false, you could delete this line, here for clarity
} else {
accum.resultList.add(action(value[0]))
accum.previousWasDupe = true
}
accum
}.resultList
}
for your test case:
val items = listOf("Q", null, "W", "E", null, "E", "E", "R", "R", "T")
println(items.processList { it + "gotcha" })
// prints "[Q, W, Egotcha, E, Rgotcha, T]"
You could use am immutable accumulator as well (I don't like it being mutable but it will perform better), but there is no point in taking that hit given the state is internal to the function. Whether this performs better as a sequence (as written) or with copies depends on the size of the lists and is hard to say without performance testing.
Notice that I also made sure the items <T>
were Comparable
so that we can be sure that ==
is doing what we expect, otherwise you really don't know you are receiving things that this function would even work upon.
For fun, the immutable version:
fun <T> List<T?>.processListImmutable(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: List<T> = emptyList(), val previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
Accumulator(accum.resultList, false) // could also be: accum.copy(previousWasDupe = false)
} else if (value.size < 2 || value[0] != value[1]) {
Accumulator(accum.resultList + value[0], false)
} else {
Accumulator(accum.resultList + action(value[0]), true)
}
}.resultList
}
An edge case to check with solutions is the input:
val items = listOf("Q", null, "W", "E", null,
"E", "E", "R", "R", "T",
"Z", "Z", "Zgotcha") // <--- this is the trap
which should return:
[Q, W, Egotcha, E, Rgotcha, T, Zgotcha, Zgotcha]
and not:
[Q, W, Egotcha, E, Rgotcha, T, Zgotchagotcha]
Here is the first pass at this, which is a bit harder functionally because some state must be maintained as you accumulate the result.
fun <T> List<T?>.processList(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: MutableList<T> = mutableListOf(), var previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
// skip this one that was already consumed in the dupe
accum.previousWasDupe = false
} else if (value.size < 2 || value[0] != value[1]) {
accum.resultList.add(value[0])
accum.previousWasDupe = false // already is false, you could delete this line, here for clarity
} else {
accum.resultList.add(action(value[0]))
accum.previousWasDupe = true
}
accum
}.resultList
}
for your test case:
val items = listOf("Q", null, "W", "E", null, "E", "E", "R", "R", "T")
println(items.processList { it + "gotcha" })
// prints "[Q, W, Egotcha, E, Rgotcha, T]"
You could use am immutable accumulator as well (I don't like it being mutable but it will perform better), but there is no point in taking that hit given the state is internal to the function. Whether this performs better as a sequence (as written) or with copies depends on the size of the lists and is hard to say without performance testing.
Notice that I also made sure the items <T>
were Comparable
so that we can be sure that ==
is doing what we expect, otherwise you really don't know you are receiving things that this function would even work upon.
For fun, the immutable version:
fun <T> List<T?>.processListImmutable(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: List<T> = emptyList(), val previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
Accumulator(accum.resultList, false) // could also be: accum.copy(previousWasDupe = false)
} else if (value.size < 2 || value[0] != value[1]) {
Accumulator(accum.resultList + value[0], false)
} else {
Accumulator(accum.resultList + action(value[0]), true)
}
}.resultList
}
An edge case to check with solutions is the input:
val items = listOf("Q", null, "W", "E", null,
"E", "E", "R", "R", "T",
"Z", "Z", "Zgotcha") // <--- this is the trap
which should return:
[Q, W, Egotcha, E, Rgotcha, T, Zgotcha, Zgotcha]
and not:
[Q, W, Egotcha, E, Rgotcha, T, Zgotchagotcha]
edited Nov 19 '18 at 15:01
answered Nov 19 '18 at 14:45
Jayson MinardJayson Minard
39.5k17109173
39.5k17109173
Thanks Jayson. Pretty impressive, I hadn't realised it was so involved, I thought I was just being a bit slow... I'm not sure about the edge case tbh, I was thinking about it, it's for an online course and sometimes you only find out the finer points of the requirement when you get the feedback (I'm not sure whether it is recursive so that Z, Z, Zgotcha should become Zgotcha, Zgotcha or Zgotchagotcha ! This is more than enough for me to take the next steps myself though! Many thanks.
– gringogordo
Nov 19 '18 at 16:02
add a comment |
Thanks Jayson. Pretty impressive, I hadn't realised it was so involved, I thought I was just being a bit slow... I'm not sure about the edge case tbh, I was thinking about it, it's for an online course and sometimes you only find out the finer points of the requirement when you get the feedback (I'm not sure whether it is recursive so that Z, Z, Zgotcha should become Zgotcha, Zgotcha or Zgotchagotcha ! This is more than enough for me to take the next steps myself though! Many thanks.
– gringogordo
Nov 19 '18 at 16:02
Thanks Jayson. Pretty impressive, I hadn't realised it was so involved, I thought I was just being a bit slow... I'm not sure about the edge case tbh, I was thinking about it, it's for an online course and sometimes you only find out the finer points of the requirement when you get the feedback (I'm not sure whether it is recursive so that Z, Z, Zgotcha should become Zgotcha, Zgotcha or Zgotchagotcha ! This is more than enough for me to take the next steps myself though! Many thanks.
– gringogordo
Nov 19 '18 at 16:02
Thanks Jayson. Pretty impressive, I hadn't realised it was so involved, I thought I was just being a bit slow... I'm not sure about the edge case tbh, I was thinking about it, it's for an online course and sometimes you only find out the finer points of the requirement when you get the feedback (I'm not sure whether it is recursive so that Z, Z, Zgotcha should become Zgotcha, Zgotcha or Zgotchagotcha ! This is more than enough for me to take the next steps myself though! Many thanks.
– gringogordo
Nov 19 '18 at 16:02
add a comment |
Try next code:
fun List<String?>.processList(action: (String) -> String): List<String> {
var remove = false
val dest = arrayListOf<String>()
return filterNotNullTo(dest).mapIndexedNotNull { index, s ->
if (remove) {
remove = false
null
} else {
if (index + 1 <= dest.lastIndex && s == dest[index + 1]) {
remove = true
action()
} else {
s
}
}
}
}
val l = listOf("Q", null, "W", "E", null, "E", "E", "R", "R", "T")
val result = l.processList {"${it}gotcha"}
This has a bug, in a case such as:val l = listOf("Z", "Z", "Zgotcha")
You cannot use the last modified value as the source of duplicate comparison. It would return["Zgotchagotcha"]
instead of["Zgotcha", "Zgotcha"]
– Jayson Minard
Nov 19 '18 at 14:57
Also you should incorporate the action lambda in the function.
– Jayson Minard
Nov 19 '18 at 14:59
1
Edited my answer including the edge case
– Sergey
Nov 19 '18 at 15:42
Your fix now introduces another edge case.val l = listOf("Z", "Z", "Zgotcha", "Zgotcha")
now does not return["Zgotcha", "Zgotchagotcha"]
as it should.
– Jayson Minard
Nov 19 '18 at 15:45
Thanks. Seems like a fair answer to me but I think of the 2 Jayson's is a better proposition.
– gringogordo
Nov 19 '18 at 15:59
|
show 1 more comment
Try next code:
fun List<String?>.processList(action: (String) -> String): List<String> {
var remove = false
val dest = arrayListOf<String>()
return filterNotNullTo(dest).mapIndexedNotNull { index, s ->
if (remove) {
remove = false
null
} else {
if (index + 1 <= dest.lastIndex && s == dest[index + 1]) {
remove = true
action()
} else {
s
}
}
}
}
val l = listOf("Q", null, "W", "E", null, "E", "E", "R", "R", "T")
val result = l.processList {"${it}gotcha"}
This has a bug, in a case such as:val l = listOf("Z", "Z", "Zgotcha")
You cannot use the last modified value as the source of duplicate comparison. It would return["Zgotchagotcha"]
instead of["Zgotcha", "Zgotcha"]
– Jayson Minard
Nov 19 '18 at 14:57
Also you should incorporate the action lambda in the function.
– Jayson Minard
Nov 19 '18 at 14:59
1
Edited my answer including the edge case
– Sergey
Nov 19 '18 at 15:42
Your fix now introduces another edge case.val l = listOf("Z", "Z", "Zgotcha", "Zgotcha")
now does not return["Zgotcha", "Zgotchagotcha"]
as it should.
– Jayson Minard
Nov 19 '18 at 15:45
Thanks. Seems like a fair answer to me but I think of the 2 Jayson's is a better proposition.
– gringogordo
Nov 19 '18 at 15:59
|
show 1 more comment
Try next code:
fun List<String?>.processList(action: (String) -> String): List<String> {
var remove = false
val dest = arrayListOf<String>()
return filterNotNullTo(dest).mapIndexedNotNull { index, s ->
if (remove) {
remove = false
null
} else {
if (index + 1 <= dest.lastIndex && s == dest[index + 1]) {
remove = true
action()
} else {
s
}
}
}
}
val l = listOf("Q", null, "W", "E", null, "E", "E", "R", "R", "T")
val result = l.processList {"${it}gotcha"}
Try next code:
fun List<String?>.processList(action: (String) -> String): List<String> {
var remove = false
val dest = arrayListOf<String>()
return filterNotNullTo(dest).mapIndexedNotNull { index, s ->
if (remove) {
remove = false
null
} else {
if (index + 1 <= dest.lastIndex && s == dest[index + 1]) {
remove = true
action()
} else {
s
}
}
}
}
val l = listOf("Q", null, "W", "E", null, "E", "E", "R", "R", "T")
val result = l.processList {"${it}gotcha"}
edited Nov 19 '18 at 19:19
answered Nov 19 '18 at 13:21
SergeySergey
3,44221732
3,44221732
This has a bug, in a case such as:val l = listOf("Z", "Z", "Zgotcha")
You cannot use the last modified value as the source of duplicate comparison. It would return["Zgotchagotcha"]
instead of["Zgotcha", "Zgotcha"]
– Jayson Minard
Nov 19 '18 at 14:57
Also you should incorporate the action lambda in the function.
– Jayson Minard
Nov 19 '18 at 14:59
1
Edited my answer including the edge case
– Sergey
Nov 19 '18 at 15:42
Your fix now introduces another edge case.val l = listOf("Z", "Z", "Zgotcha", "Zgotcha")
now does not return["Zgotcha", "Zgotchagotcha"]
as it should.
– Jayson Minard
Nov 19 '18 at 15:45
Thanks. Seems like a fair answer to me but I think of the 2 Jayson's is a better proposition.
– gringogordo
Nov 19 '18 at 15:59
|
show 1 more comment
This has a bug, in a case such as:val l = listOf("Z", "Z", "Zgotcha")
You cannot use the last modified value as the source of duplicate comparison. It would return["Zgotchagotcha"]
instead of["Zgotcha", "Zgotcha"]
– Jayson Minard
Nov 19 '18 at 14:57
Also you should incorporate the action lambda in the function.
– Jayson Minard
Nov 19 '18 at 14:59
1
Edited my answer including the edge case
– Sergey
Nov 19 '18 at 15:42
Your fix now introduces another edge case.val l = listOf("Z", "Z", "Zgotcha", "Zgotcha")
now does not return["Zgotcha", "Zgotchagotcha"]
as it should.
– Jayson Minard
Nov 19 '18 at 15:45
Thanks. Seems like a fair answer to me but I think of the 2 Jayson's is a better proposition.
– gringogordo
Nov 19 '18 at 15:59
This has a bug, in a case such as:
val l = listOf("Z", "Z", "Zgotcha")
You cannot use the last modified value as the source of duplicate comparison. It would return ["Zgotchagotcha"]
instead of ["Zgotcha", "Zgotcha"]
– Jayson Minard
Nov 19 '18 at 14:57
This has a bug, in a case such as:
val l = listOf("Z", "Z", "Zgotcha")
You cannot use the last modified value as the source of duplicate comparison. It would return ["Zgotchagotcha"]
instead of ["Zgotcha", "Zgotcha"]
– Jayson Minard
Nov 19 '18 at 14:57
Also you should incorporate the action lambda in the function.
– Jayson Minard
Nov 19 '18 at 14:59
Also you should incorporate the action lambda in the function.
– Jayson Minard
Nov 19 '18 at 14:59
1
1
Edited my answer including the edge case
– Sergey
Nov 19 '18 at 15:42
Edited my answer including the edge case
– Sergey
Nov 19 '18 at 15:42
Your fix now introduces another edge case.
val l = listOf("Z", "Z", "Zgotcha", "Zgotcha")
now does not return ["Zgotcha", "Zgotchagotcha"]
as it should.– Jayson Minard
Nov 19 '18 at 15:45
Your fix now introduces another edge case.
val l = listOf("Z", "Z", "Zgotcha", "Zgotcha")
now does not return ["Zgotcha", "Zgotchagotcha"]
as it should.– Jayson Minard
Nov 19 '18 at 15:45
Thanks. Seems like a fair answer to me but I think of the 2 Jayson's is a better proposition.
– gringogordo
Nov 19 '18 at 15:59
Thanks. Seems like a fair answer to me but I think of the 2 Jayson's is a better proposition.
– gringogordo
Nov 19 '18 at 15:59
|
show 1 more 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%2f53374448%2fhow-to-iterate-a-list-of-characters-and-compare-different-elements%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