More list functions

mrangel
22 Mar 2018, 15:15

Hey folks!
I've found a few times that I'm writing extra functions to do something with a list, and I thought it might be good to roll out a function that will take care of most list-editing functions.
This is loosely based on the behaviour of Perl's splice function, which seems to do just about everything you might want. Anyone find this useful?

Some code...
<function name="ListSplice" parameters="list, start, length, replacements" type="list"><![CDATA[
  removed = NewList()
  output = NewList()
  original_length = length
  original_replacements = replacements
  if (TypeOf(start) = "int") {
    if (start < 0) {
      start = start + LengthOf(list)
    }
  }
  else if (ListContains(list, start)) {
    start = IndexOf(list, start)
  }
  else if (TypeOf(start) = "null"){
    start = ListCount (list)
  }
  else if (not EndsWith(TypeOf(start), "list")) {
    return (null)
  }
  if (TypeOf(length) = "int") {
    if (length < 0) {
      length = length + ListCount(list) - start
    }
  }
  else if (TypeOf(length) = "null") {
    length = ListCount(list)
  }
  copying = true
  while (LengthOf(list) > 0) {
    item = ListItem(list, 0)
    if (copying) {
      if (EndsWith(TypeOf(start), "list")) {
        if (ListContains(start, item)) {
          list remove (start, item)
          copying = false
        }
        else if (start > 0) {
          start = start - 1
        }
        else {
          copying = false
        }
      }
    }
    if (copying) {
      list add (output, item)
    }
    else {
      if (not TypeOf(replacements) = "null") {
        if (EndsWith(TypeOf(replacements), "list")) {
          foreach (r, replacements) {
            list add (output, r)
          }
          replacements = null
        }
        else {
          list add (output, replacements)
        }
      }
      if (not TypeOf(length) = "int") {
        if (EndsWith(TypeOf(length), "list")) {
          if (ListContains(length, item)) {
            length = 0
          }
        }
        if (Equal(item, length)) {
          length = 0
        }
        list add (removed, item)
      }
      else if (length > 0) {
        length = length - 1
        list add (removed, item)
      }
      else {
        list add (list, item)
      }
      if (Equal(length, 0) and EndsWith(TypeOf(start), "list")) {
        length = original_length
        replacements = original_replacements
        copying = true
      }
    }
    list remove (list, item)
  }
  foreach (item, output) {
    list add (list, item)
  }
  return (removed)
]]></function>

The command is:
ListSplice (list, start, length, replacements)

This can add or remove elements from a list. It returns a list of the elements removed, in case you need them.

Arguments:

  • list - The list to modify
  • start - Where to start. It can be:
    • A positive number - Number of the first element to remove
    • A negative number - Number from the end of the list
    • Zero - the elements are removed/inserted at the start of the list
    • null - elements from replacement are inserted at the end of the list
    • An object/string/whatever - remove the specified element from the list if it exists
      • If it's not in the list, do nothing
    • A list - as if the function was called for each of the elements in the list
      • So if "start" is Split("apple;banana;fish") and length is 2, it will remove those three elements and the elements immediately after them
  • length - Where to stop removing elements. Can be:
    • Zero - don't remove any elements; just insert replacement before the element specified by start
    • A positive number - remove that number of elements, starting with the one specified by start
    • A negative number - remove elements, leaving this number at the end of the list
    • null - remove all elements from start to the end of the list
    • A string/object/other - remove elements up to and including one that's equal to this element if it exists
      • If it's not in the list, remove all elements to the end of the list
      • If length is a list, remove elements up to and including any of the elements in it
  • replacement - What to replace the removed elements with, or what to insert.
    • null - Don't insert anything, just remove
    • A list - add these elements in place of the removed ones, or before the start element if nothing is removed
    • Any other data type - replace each removed element with this value

Examples:

  • ListSplice (somelist, 0, 3, null) - removes (and returns) the first 3 elements from somelist
  • ListSplice (somelist, -3, null, null) - removes (and returns) the last 3 elements from somelist
  • ListSplice (somelist, 0, -3, null) - removes (and returns) all except the last 3 elements from somelist
  • ListSplice (somelist, -2, 1, "Heee's coming!") - replaces the penultimate element of list with "Heee's coming!", and return what it was before
  • ListSplice (somelist, null, 0, Split("a;b;c")) - adds 3 strings to the end of somelist
  • ListSplice (somelist, "turn left", 1, "No, your other left!") - replaces the first instance of "turn left" with "No, your other left!"
  • ListSplice (somelist, "D", -2, "Nyuk!") - replaces the element "D" if it exists, and all subsequent elements except the last two, with "Nyuk!"