#Is there a built-in function to search a string for the starting index of a given substring?

1 messages · Page 1 of 1 (latest)

hallow cape
#

Something similar to javascript String.prototype.indexOf()

twin halo
#

no, doesn't look like it

misty fossil
#

It is relatively easy to write one:

pub fn index_of(haystack: String, needle: String) -> Int {
  let needle_graphemes = string.to_graphemes(needle)
  let needle_length = list.length(needle_graphemes)

  haystack
  |> string.to_graphemes
  |> list.window(needle_length)
  |> list.index_fold(from: -1, with: fn(acc, item, index) {
    case item == needle_graphemes {
      True -> index
      False -> acc
    }
  })
}
#

Altho it's good to note, indexing is not really a gleamy pattern.

noble tide
#

Maybe you could do a regex search

#

Wait nvm the regex match doesn't give you the index lucydebugfail

hallow cape
misty fossil
#

There's no way to do an early return / break, so we need to process the entire list

#

But the solution can be modified to keep the first match

#

For default parameters, the gleamy way is usually to provide a function with sane defaults, and to provide another one with all the bells-whistles-parameterization

opaque moth
#

How about

pub fn main() {
  let _ = index_of("", in: "Hello, world!") |> io.debug
  let _ = index_of("Hello", in: "Hello, world!") |> io.debug
  let _ = index_of("world", in: "Hello, world!") |> io.debug
  index_of("bye", in: "Hello, world!") |> io.debug
}

pub fn index_of(sub part: String, in whole: String) -> Result(Int, Nil) {
  do_index_of(part, whole, 0)
}

fn do_index_of(part, whole, index) {
  case string.starts_with(part, whole) {
    True -> Ok(index)
    False -> case whole {
      "" -> Error(Nil)
      _ -> do_index_of(part, string.drop_left(whole, 1), index + 1)
    }
  }
}

use a function from stdlib to compare (assuming that is most efficient); recursion to stop when match found

#

(except the code above doesn't work correctly)

#

now it does