sarat1669
Is there a better way to swap elements in a list?
Any inbuilt function or a library?
defmodule SwapElements do
def swap(list, first_index, second_index) do
{a, b} = split(list, first_index + 1)
{x, y} = split(b, second_index - first_index)
[h1 | t1] = a
[h2 | t2] = x
y
|> reverse_append([h1])
|> reverse_append(t2)
|> reverse_append([h2])
|> reverse_append(t1)
end
def split(list, n) do
split([], list, n)
end
def split(a, b, 0) do
{a, b}
end
def split(list, [h|t], n) do
split([h | list], t, n - 1)
end
def reverse_append(list, []) do
list
end
def reverse_append(list, [h | t]) do
reverse_append([h | list], t)
end
end
iex(27)> SwapElements.swap(Enum.to_list(0..10), 1, 4)
[0, 4, 2, 3, 1, 5, 6, 7, 8, 9, 10]
Trending in Questions
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
Hello,
I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
sarat1669
Shower Thought:
If lists in beam were implemented as
XOR linked listThey can be be reversed in O(1)
al2o3cr
Here are two possible approaches using functions from
EnumandList:Beware that both of these (just like the one in your post) have
O(N)time-complexity since they have to traverse the entire list.benwilson512
Swap2 is definitely the most clear imho, nice stuff.
@sarat1669 It’s probably worth noting that if you want to perform a bunch of index based changes to a “list” you are probably better off using a map with the indices as keys rather than a list, which just really isn’t setup for efficient index based access or changes.
sarat1669
@al2o3cr Enum.split will be doing a Enum.reverse internally right?
I was trying to avoid that
Edit:
https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/enum.ex#L2762
sarat1669
@benwilson512 I think the ordering will not be maintained in a Map.
It might be a good alternative for accessing and updating and not for the other cases.
egze
You could also use the
:arraymodule from Erlang.al2o3cr
It’s a tradeoff between reducing the constant factor of an
O(N)algorithm versus readability.If performance is a concern, the better solution is to pick a more-efficient data structure for the operations you want to do. For instance, the
:arraymodule mentioned by @egze uses a 10-way tree made of tuples. The source has some additional notes about why they chose 10:https://github.com/erlang/otp/blob/00503c64bc321fc1d2ff1233613debf2f579cedb/lib/stdlib/src/array.erl#L108-L126
Also note that
:array.from_listand:array.to_listboth have to traverse the whole list, so if you’re doing a lot of swaps you’ll want to keep your data in the:arraystructure.Qqwy
There are a couple of libraries implementing such higher-performance persistent sequential data structures. A couple of years back I wrote Arrays which has a single interface with pluggable backends for either
:arraysor “maps with indices as keys”, as well as implementing many useful protocols like Enumerable, Collectable, Access, etc. to allow you to keep your code idiomatic and easily change between one Enumerable backend and another.Other algorithms exist as well. For instance, there is a library called Hallux that has a sequential data structure with amortized O(1) element access based on finger trees, and PersistentVector based on 32-way tries.
al2o3cr
I don’t know when this would ever be useful, but here’s a version of
swapthat even works on infinite streams!This uses
Stream.transformwith a reducer function that implements a tiny state machine to handle the change in behavior when the two indexes are passed.It also chains:
While it’s a streaming algorithm, it still needs to hold at least
i2-i1intermediate elements in memory since it can’t produce thei1th element until it’s seen thei2th.Also beware:
Swap3.swapdoes weird things if the supplied indexes aren’t in order (i1 < i2) or are equal.dkuku
I tough recursion will be the most performant way here and I think it is but implementation is quite long.
It’s still O(n) but probably 2x as performant as twice using replace_at