File 5351-Adding-lists-uniq-1-and-lists-uniq-2.patch of Package erlang

From de65b7f94dd846fbebc3d64272495da623197bab Mon Sep 17 00:00:00 2001
From: Gian Lorenzo Meocci <glmeocci@gmail.com>
Date: Thu, 3 Mar 2022 10:31:05 +0100
Subject: [PATCH] Adding lists:uniq/1 and lists:uniq/2

---
 lib/stdlib/doc/src/lists.xml    | 37 +++++++++++++++++++++++++++
 lib/stdlib/src/lists.erl        | 45 +++++++++++++++++++++++++++++++--
 lib/stdlib/test/lists_SUITE.erl | 28 +++++++++++++++++---
 3 files changed, 105 insertions(+), 5 deletions(-)

diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml
index 063c9d19a8..8b39279b48 100644
--- a/lib/stdlib/doc/src/lists.xml
+++ b/lib/stdlib/doc/src/lists.xml
@@ -1126,6 +1126,43 @@ splitwith(Pred, List) ->
 [[a,x,1],[b,y,2],[c,z,3]]</pre>
       </desc>
     </func>
+
+    <func>
+      <name name="uniq" arity="1" since="OTP 25.0"/>
+      <fsummary>Removes duplicate elements of a list preserving the order.</fsummary>
+      <desc>
+        <p>Returns a list containing the elements of
+        <c><anno>List1</anno></c> with duplicated elements removed
+        (preserving the order of the elements).  The first occurrence of
+        each element is kept.</p>
+        <p><em>Examples:</em></p>
+        <pre>
+> <input>lists:uniq(fun([3,3,1,2,1,2,3]).</input>
+[3,1,2]
+> <input>lists:uniq([a, a, 1, b, 2, a, 3]).</input>
+[a, 1, b, 2, 3]</pre>
+      </desc>
+    </func>
+
+    <func>
+      <name name="uniq" arity="2" since="OTP 25.0"/>
+      <fsummary>
+        Removes duplicate elements of a list using
+        a fun as a key preserving the order.
+      </fsummary>
+      <desc>
+        <p>Returns a list containing the elements of
+        <c><anno>List1</anno></c> without the elements for which
+        <c><anno>Fun</anno></c> returned duplicate values
+        (preserving the order of the elements).  The first occurrence
+        of each element is kept.</p>
+        <p><em>Examples:</em></p>
+        <pre>
+> <input>lists:uniq(fun({X, _}) -> X end, [{b, 2}, {a, 1}, {c, 3}, {a, 2}]).</input>
+[{b, 2}, {a, 1}, {c, 3}]</pre>
+      </desc>
+    </func>
+
   </funcs>
 </erlref>
 
diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl
index 2a9122384b..96898a88f5 100644
--- a/lib/stdlib/src/lists.erl
+++ b/lib/stdlib/src/lists.erl
@@ -36,7 +36,7 @@
          prefix/2, reverse/1, seq/2, seq/3,
          split/2, sublist/2, sublist/3,
          subtract/2, suffix/2, sum/1,
-         unzip/1, unzip3/1,
+         uniq/1, unzip/1, unzip3/1,
          zip/2, zip3/3]).
 
 %% Functions taking a list of tuples and a position within the tuple.
@@ -59,7 +59,7 @@
          foldl/3, foldr/3, foreach/2,
          map/2, mapfoldl/3, mapfoldr/3,
          partition/2, search/2,
-         splitwith/2, takewhile/2,
+         splitwith/2, takewhile/2, uniq/2,
          zipwith/3, zipwith3/4]).
 
 %% Undocumented, but used within Erlang/OTP.
@@ -2975,3 +2975,44 @@ rufmerge2_2(H1, T1, Fun, [], M, H2M) ->
             lists:reverse(T1, [H1, H2M | M])
     end.
 
+%% uniq/1: return a new list with the unique elements of the given list
+
+-spec uniq(List1) -> List2 when
+      List1 :: [T],
+      List2 :: [T],
+      T :: term().
+
+uniq(L) ->
+    uniq_1(L, #{}).
+
+uniq_1([X | Xs], M) ->
+    case is_map_key(X, M) of
+        true ->
+            uniq_1(Xs, M);
+        false ->
+            [X | uniq_1(Xs, M#{X => true})]
+    end;
+uniq_1([], _) ->
+    [].
+
+%% uniq/2: return a new list with the unique elements of the given list using a function key
+
+-spec uniq(Fun, List1) -> List2 when
+      Fun :: fun((T) -> any()),
+      List1 :: [T],
+      List2 :: [T],
+      T :: term().
+
+uniq(F, L) when is_function(F, 1) ->
+    uniq_2(L, F, #{}).
+
+uniq_2([X | Xs], F, M) ->
+    Key = F(X),
+    case is_map_key(Key, M) of
+        true ->
+            uniq_2(Xs, F, M);
+        false ->
+            [X | uniq_2(Xs, F, M#{Key => true})]
+    end;
+uniq_2([], _, _) ->
+    [].
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index 68fb1cd92f..26b71887fa 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -32,7 +32,7 @@
 %% Test cases must be exported.
 -export([member/1, reverse/1,
 	 keymember/1, keysearch_keyfind/1,
-         keystore/1, keytake/1, keyreplace/1,
+	 keystore/1, keytake/1, keyreplace/1,
 	 append_1/1, append_2/1,
 	 seq_loop/1, seq_2/1, seq_3/1, seq_2_e/1, seq_3_e/1,
 
@@ -53,6 +53,7 @@
 	 ufunmerge/1, rufunmerge/1,
 	 ufunsort_1/1, ufunsort_stable/1, ufunsort_rand/1,
 	 ufunsort_error/1,
+	 uniq_1/1, uniq_2/1,
 	 zip_unzip/1, zip_unzip3/1, zipwith/1, zipwith3/1,
 	 filter_partition/1, 
 	 join/1,
@@ -81,10 +82,11 @@ suite() ->
 all() -> 
     [{group, append},
      {group, key},
-     {group,sort},
+     {group, sort},
      {group, usort},
      {group, keysort},
      {group, ukeysort},
+     {group, uniq},
      {group, funsort},
      {group, ufunsort},
      {group, sublist},
@@ -120,6 +122,7 @@ groups() ->
       [flatten_1, flatten_2, flatten_1_e, flatten_2_e]},
      {tickets, [parallel], [otp_5939, otp_6023, otp_6606, otp_7230]},
      {zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]},
+     {uniq, [parallel], [uniq_1, uniq_2]},
      {misc, [parallel], [reverse, member, dropwhile, takewhile,
 			 filter_partition, suffix, subtract, join,
 			 hof, droplast, search, enumerate]}
@@ -2758,3 +2761,22 @@ enumerate(Config) when is_list(Config) ->
     {'EXIT', {function_clause, _}} = catch lists:enumerate(1, <<1,2,3>>),
 
     ok.
+
+uniq_1(_Config) ->
+    [] = lists:uniq([]),
+    [foo] = lists:uniq([foo]),
+    ["foo", "bar", "zoo"] = lists:uniq(["foo", "foo", "bar", "foo", "zoo",
+                                        "foo", "bar", "zoo"]),
+    [a, 1, b, 2] = lists:uniq([a, a, a, 1, b, 2, a, 2, 1]),
+    [<<"home">>, "home"] = lists:uniq([<<"home">>, "home"]),
+    [3.14159, 2.71828, 3.17] = lists:uniq([3.14159, 3.14159, 2.71828, 3.17]),
+    [42, 42.0] = lists:uniq([42, 42.0, 42, 42.0]),
+    ok.
+
+uniq_2(_Config) ->
+    [] = lists:uniq(fun(X) -> X end, []),
+    [{42, 1}, {42.0, 99}, {a, 99}] =
+        lists:uniq(fun(X) -> element(1, X) end,
+                   [{42, 1}, {42.0, 99}, {a, 99}, {a, 1}, {42, 100}]),
+    [1] = lists:uniq(fun(_) -> whatever end, lists:seq(1, 10)),
+    ok.
-- 
2.34.1

openSUSE Build Service is sponsored by