Sebb

Sebb

String.split vs Enum.split_with

There seems to be no way to split an Enum like String.split does. Actually those functions have very different semantics.

String.split("123045067809", "0") #=> ["123", "45", "678", "9"]

function I’d like to have:

l =  [1,2,3,0,4,5,0,6,7,8,0,9]
Enum.split(l, &(&1 == 0)) #=>[[1, 2, 3], [4, 5], [6, 7, 8], [9]]

this is there, but not what I want:

Enum.split_with(l, &(&1 == 0)) #=> {[0, 0, 0], [1, 2, 3, 4, 5, 6, 7, 8, 9]}

close:

Enum.chunk_by(l, &(&1 == 0)) #=> [[1, 2, 3], [0], [4, 5], [0], [6, 7, 8], [0], '\t']

I think this is the first time, I miss a funciton in stdlib, that I expected to be there.

String.split(string, pattern, options \\ [])

Divides a string into parts based on a pattern. [split]

Enum.split_with(enumerable, fun)

Splits the enumerable in two lists according to the given function fun. [split_with]

Marked As Solved

dimitarvp

dimitarvp

You can just pipe the chunk_by result like this: |> Enum.reject(&1 == [0])?

Also Liked

adamu

adamu

Obligatory benchmarks.

Name                      ips        average  deviation         median         99th %
recursion              3.98 M      251.49 ns ±11214.50%         188 ns         456 ns
foldr                  2.99 M      334.99 ns ±12387.85%         223 ns         506 ns
reduce                 2.70 M      370.10 ns  ±9843.80%         258 ns         567 ns
chunk_while            1.40 M      712.55 ns  ±4515.89%         532 ns         968 ns
chunk_by_reject        0.86 M     1164.60 ns  ±2888.22%         896 ns        1427 ns

Comparison:
recursion              3.98 M
foldr                  2.99 M - 1.33x slower +83.50 ns
reduce                 2.70 M - 1.47x slower +118.61 ns
chunk_while            1.40 M - 2.83x slower +461.06 ns
chunk_by_reject        0.86 M - 4.63x slower +913.11 ns

Operating System: macOS
CPU Information: Intel(R) Core(TM) i5-6600 CPU @ 3.30GHz
Number of Available Cores: 4
Available memory: 24 GB
Elixir 1.14.0
Erlang 25.0

Out of curiosity, I included this reduce version too:

Enum.reduce(list, {_group = [], _acc = []}, fn
  0, {[], acc} -> {[], acc}
  0, {group, acc} -> {[], [Enum.reverse(group) | acc]}
  el, {group, acc} -> {[el | group], acc}
end)
|> case do
  {[], acc} -> Enum.reverse(acc)
  {group, acc} -> Enum.reverse([Enum.reverse(group) | acc])
end
Eiji

Eiji

Here you go:

defmodule Example do
  def sample(list) when is_list(list) do
    # we start with one empty list
    List.foldr(list, [[]], fn
      # in case we got 0
      # we are adding new empty list at beginning of result
      0, acc -> [[] | acc]
      # otherwise we are appending element
      # as a head of first list in result
      element, [head | tail] -> [[element | head] | tail]
    end)
  end
end

[1, 2, 3, 0, 4, 5, 0, 6, 7, 8, 0, 9]
|> Example.sample()
|> IO.inspect(charlists: :as_lists)
# [[1, 2, 3], [4, 5], [6, 7, 8], [9]]

See List.foldr/3 documentation.

hst337

hst337

Actually, this is not that hard to write. Just

def split(list, splitter, acc \\ [])
def split([], _, []), do: []
def split([], _, acc), do: [:lists.reverse acc]
def split([splitter | tail], splitter, acc) do
  [:lists.reverse(acc) | split(tail, splitter, [])]
end
def split([item | tail], splitter, acc) do
  split(tail, splitter, [item | acc])
end
adamu

adamu

iex(2)> l |> Enum.join() |> String.split("0")
["123", "45", "678", "9"]

:troll:

Interesting though, especially as Enum.intersperse/2 exists.

LostKobrakai

LostKobrakai

Not much shorter, but using Enum instead of recursion:

l =  [1,2,3,0,4,5,0,6,7,8,0,9]

Enum.chunk_while(l, [], fn 
  0, acc -> {:cont, Enum.reverse(acc), []}
  element, acc -> {:cont, [element | acc]}
end, fn
  [] -> {:cont, []}
  acc -> {:cont, Enum.reverse(acc), []}
end)
# [[1, 2, 3], [4, 5], [6, 7, 8], [9]]

Where Next?

Popular in Questions Top

yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
Fl4m3Ph03n1x
Background Let’s assume I have a typical GenServer that receives messages as requests, does some operation in a DB and returns responses....
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics Top

JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

We're in Beta

About us Mission Statement