Files
n8n-openai-adapter/lib/keyword.ex
T
2012-05-13 15:33:57 +02:00

227 lines
5.8 KiB
Elixir

defmodule Keyword do
@moduledoc """
A keyword is a list of tuples where the first element
of the tuple is an atom and the second element can be
any value. The list is sorted by the first element of
each tuple.
A keyword may have duplicated keys, so it is not strictly
a dictionary. However most of the functions in this module
allows it to behave exactly as a dictionary. For example,
`Keyword.get` will get the first entry matching the given
key, regardless if duplicated entries exist. Similarly,
`Keyword.put` and `Keyword.delete` ensure all duplicated
entries for a given key are removed when invoked.
This module uses `==` as operator to check if two keys
are equal or not.
"""
@doc """
Creates a Keyword from enum. Differently from `Keyword.new`
that behaves as a dict, `Keyword.from_enum` do not remove
duplicated entries.
"""
def from_enum(enum) do
Enum.qsort(enum)
end
@doc """
Returns an empty keywords list, i.e. an empty list.
"""
def new do
[]
end
@doc """
Creates a Keyword from an enumerable. Similarly to dicts,
duplicated entries are removed, the latest one prevails.
## Examples
Keyword.new [{:b,1},{:a,2}]
#=> [a: 2, b: 1]
"""
def new(pairs) do
Enum.reduce pairs, [], fn {k, v}, keywords ->
put(keywords, k, v)
end
end
@doc """
Creates a Keyword from an enumerable with the
help of the transformation function. Duplicated
entries are removed, the latest one prevails.
## Examples
Keyword.new [:a, :b], fn x -> {x,x} end
#=> [a: :a, b: :b]
"""
def new(pairs, transform) do
Enum.reduce pairs, [], fn i, keywords ->
{ k, v } = transform.(i)
put(keywords, k, v)
end
end
@doc """
Gets the value for specific key.
If key not exist return default value (nil if no default value)
exists.
If duplicated entries exist, the first one is returned.
Use get_values/2 to retrieve all entries.
## Examples
Keyword.get [a: 1], :a #=> 1
Keyword.get [a: 1], :b #=> nil
Keyword.get [a: 1], :b, 3 #=> 3
"""
def get(keywords, key, default // nil)
def get([{k, _}|_], key, default) when key < k, do: default
def get([{k, _}|d], key, default) when key > k, do: get(d, key, default)
def get([{_, value}|_], _key, _default), do: value
def get([], _, default), do: default
@doc """
Gets all values for a specific key.
## Examples
Keyword.get_values [a: 1, a: 2], :a
#=> [1,2]
"""
def get_values([{k, _}|_], key) when key < k, do: []
def get_values([{k, _}|d], key) when key > k, do: get_values(d, key)
def get_values([{_, value}|d], key), do: [value|get_values(d, key)]
def get_values([], _), do: []
@doc """
Returns all keys from the keywords list. Duplicated
keys appear duplicated in the final list of keys.
## Examples
Keyword.keys [a: 1, b: 2] #=> [:a,:b]
"""
def keys(keywords) do
lc { key, _ } in keywords, do: key
end
@doc """
Returns all values.
## Examples
Keyword.values [a: 1, b: 2] #=> [1,2]
"""
def values(keywords) do
lc { _, value } in keywords, do: value
end
@doc """
Deletes all entries in the keywords list for a specific key.
If the key does not exist, returns the keywords list unchanged.
Use `delete_first` to delete just the first entry in case of
duplicated keys.
## Examples
Keyword.delete [a: 1, b: 2], :a #=> [b: 2]
Keyword.delete [b: 2], :a #=> [b: 2]
"""
def delete([{k, _}|_] = keywords, key) when key < k, do: keywords
def delete([{k, _} = e|tail], key) when key > k, do: [e|delete(tail, key)]
def delete([{_, _}|tail], key), do: delete(tail, key)
def delete([], _), do: []
@doc """
Sets the given `value` under `key`.
If a previous value is already stored, all entries are
removed and the value is overriden.
Use `put_other/3` to add a new value for an existing key
without removing previous ones.
## Examples
Keyword.put [a: 1, b: 2], :a, 3
#=> [a: 3, b: 2]
"""
def put([{k, _} = e|keywords], key, value) when key < k and is_atom(key) do
[{key, value},e|keywords]
end
def put([{k, _} = e|keywords], key, value) when key > k do
[e|put(keywords, key, value)]
end
def put([{key, _}|keywords], key, value) when is_atom(key) do
[{key, value}|delete(keywords, key)]
end
def put([], key, value) when is_atom(key) do
[{key, value}]
end
@doc """
Merges two keywords lists into one. If they have duplicated
entries, the one given as second argument wins.
## Examples
Keyword.merge [a: 1, b: 2], [a: 3, d: 4]
#=> [a:3, b:2, d: 4]
"""
def merge(d1, d2) do
merge(d1, d2, fn _k, _v1, v2 -> v2 end)
end
@doc """
Merges two keywords lists into one. If they have duplicated
entries, the given function is invoked to solve conflicts.
## Examples
Keyword.merge [a: 1, b: 2], [a: 3, d: 4], fn _k, v1, v2 ->
v1 + v2
end
#=> [a:4, b:2, d: 4]
"""
def merge([{k1, _} = e1|d1], [{k2, _} = e2|d2], fun) when k1 < k2 and is_atom(k1) do
[e1|merge(d1, [e2|d2], fun)]
end
def merge([{k1, _} = e1|d1], [{k2, _} = e2|d2], fun) when k1 > k2 and is_atom(k2) do
[e2|merge([e1|d1], d2, fun)]
end
def merge([{k1, v1}|d1], [{k1, v2}|d2], fun) do
[{k1, fun.(k1, v1, v2)}|merge(d1, d2, fun)]
end
def merge([], d2, _fun), do: d2
def merge(d1, [], _fun), do: d1
@doc """
Returns whether a given key exists in the given keywords.
### Examples
Keyword.key?([a: 1], :a)
#=> true
Keyword.key?([a: 1], :b)
#=> false
"""
def key?([{k, _}|_], key) when key < k, do: false
def key?([{k, _}|d], key) when key > k, do: key?(d, key)
def key?([{_, _}|_], _key), do: true
def key?([], _), do: false
end