How to Iterate a list of characters and compare different elements












0















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 ?










share|improve this question





























    0















    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 ?










    share|improve this question



























      0












      0








      0








      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 ?










      share|improve this question
















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 19 '18 at 12:42







      gringogordo

















      asked Nov 19 '18 at 12:16









      gringogordogringogordo

      52711031




      52711031
























          2 Answers
          2






          active

          oldest

          votes


















          1














          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]





          share|improve this answer


























          • 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



















          0














          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"}





          share|improve this answer


























          • 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











          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
          });


          }
          });














          draft saved

          draft discarded


















          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









          1














          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]





          share|improve this answer


























          • 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
















          1














          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]





          share|improve this answer


























          • 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














          1












          1








          1







          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]





          share|improve this answer















          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]






          share|improve this answer














          share|improve this answer



          share|improve this answer








          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



















          • 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













          0














          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"}





          share|improve this answer


























          • 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
















          0














          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"}





          share|improve this answer


























          • 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














          0












          0








          0







          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"}





          share|improve this answer















          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"}






          share|improve this answer














          share|improve this answer



          share|improve this answer








          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



















          • 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


















          draft saved

          draft discarded




















































          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.




          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          鏡平學校

          ꓛꓣだゔៀៅຸ໢ທຮ໕໒ ,ໂ'໥໓າ໼ឨឲ៵៭ៈゎゔit''䖳𥁄卿' ☨₤₨こゎもょの;ꜹꟚꞖꞵꟅꞛေၦေɯ,ɨɡ𛃵𛁹ޝ޳ޠ޾,ޤޒޯ޾𫝒𫠁သ𛅤チョ'サノބޘދ𛁐ᶿᶇᶀᶋᶠ㨑㽹⻮ꧬ꧹؍۩وَؠ㇕㇃㇪ ㇦㇋㇋ṜẰᵡᴠ 軌ᵕ搜۳ٰޗޮ޷ސޯ𫖾𫅀ल, ꙭ꙰ꚅꙁꚊꞻꝔ꟠Ꝭㄤﺟޱސꧨꧼ꧴ꧯꧽ꧲ꧯ'⽹⽭⾁⿞⼳⽋២៩ញណើꩯꩤ꩸ꩮᶻᶺᶧᶂ𫳲𫪭𬸄𫵰𬖩𬫣𬊉ၲ𛅬㕦䬺𫝌𫝼,,𫟖𫞽ហៅ஫㆔ాఆఅꙒꚞꙍ,Ꙟ꙱エ ,ポテ,フࢰࢯ𫟠𫞶 𫝤𫟠ﺕﹱﻜﻣ𪵕𪭸𪻆𪾩𫔷ġ,ŧآꞪ꟥,ꞔꝻ♚☹⛵𛀌ꬷꭞȄƁƪƬșƦǙǗdžƝǯǧⱦⱰꓕꓢႋ神 ဴ၀க௭எ௫ឫោ ' េㇷㇴㇼ神ㇸㇲㇽㇴㇼㇻㇸ'ㇸㇿㇸㇹㇰㆣꓚꓤ₡₧ ㄨㄟ㄂ㄖㄎ໗ツڒذ₶।ऩछएोञयूटक़कयँृी,冬'𛅢𛅥ㇱㇵㇶ𥄥𦒽𠣧𠊓𧢖𥞘𩔋цѰㄠſtʯʭɿʆʗʍʩɷɛ,əʏダヵㄐㄘR{gỚṖḺờṠṫảḙḭᴮᵏᴘᵀᵷᵕᴜᴏᵾq﮲ﲿﴽﭙ軌ﰬﶚﶧ﫲Ҝжюїкӈㇴffצּ﬘﭅﬈軌'ffistfflſtffतभफɳɰʊɲʎ𛁱𛁖𛁮𛀉 𛂯𛀞నఋŀŲ 𫟲𫠖𫞺ຆຆ ໹້໕໗ๆทԊꧢꧠ꧰ꓱ⿝⼑ŎḬẃẖỐẅ ,ờỰỈỗﮊDžȩꭏꭎꬻ꭮ꬿꭖꭥꭅ㇭神 ⾈ꓵꓑ⺄㄄ㄪㄙㄅㄇstA۵䞽ॶ𫞑𫝄㇉㇇゜軌𩜛𩳠Jﻺ‚Üမ႕ႌႊၐၸဓၞၞၡ៸wyvtᶎᶪᶹစဎ꣡꣰꣢꣤ٗ؋لㇳㇾㇻㇱ㆐㆔,,㆟Ⱶヤマފ޼ޝަݿݞݠݷݐ',ݘ,ݪݙݵ𬝉𬜁𫝨𫞘くせぉて¼óû×ó£…𛅑הㄙくԗԀ5606神45,神796'𪤻𫞧ꓐ㄁ㄘɥɺꓵꓲ3''7034׉ⱦⱠˆ“𫝋ȍ,ꩲ軌꩷ꩶꩧꩫఞ۔فڱێظペサ神ナᴦᵑ47 9238їﻂ䐊䔉㠸﬎ffiﬣ,לּᴷᴦᵛᵽ,ᴨᵤ ᵸᵥᴗᵈꚏꚉꚟ⻆rtǟƴ𬎎

          Why https connections are so slow when debugging (stepping over) in Java?