我在erlang中包含整數值的列表。 我想刪除只發生一次的值(不重複)。刪除列表元素只出現一次
Input = [1,3,2,1,2,2]
Output = [1,2,1,2,2]
我是erlang的新手。我嘗試了一種方法,首先使用list:sort()
對它們進行排序,然後刪除一個成員,如果它旁邊的成員相同。 我在嘗試迭代列表時遇到了問題。如果你能告訴我我該怎麼做,這將是非常有幫助的。
我在erlang中包含整數值的列表。 我想刪除只發生一次的值(不重複)。刪除列表元素只出現一次
Input = [1,3,2,1,2,2]
Output = [1,2,1,2,2]
我是erlang的新手。我嘗試了一種方法,首先使用list:sort()
對它們進行排序,然後刪除一個成員,如果它旁邊的成員相同。 我在嘗試迭代列表時遇到了問題。如果你能告訴我我該怎麼做,這將是非常有幫助的。
使用地圖計數的值,然後過濾這是不存在的只是一次值。
-module(test).
-export([remove_unique/1]).
remove_unique(L) ->
Count = lists:foldl(fun count/2, #{}, L),
lists:filter(fun(X) -> maps:get(X, Count) =/= 1 end, L).
count(X, M) ->
maps:put(X, maps:get(X, M, 0) + 1, M).
和測試:
1> c(test).
{ok,test}
2> test:remove_unique([1,2,3,3,3,5,5,6,7,7]).
[3,3,3,5,5,7,7]
3> test:remove_unique([1,2,3,3,3,5,5,6,7,8]).
[3,3,3,5,5]
4> test:remove_unique([1,3,2,1,2,2]).
[1,2,1,2,2]
迭代列表的一種方式(作爲結果將返回一個新列表)正在使用遞歸和模式匹配。
在對列表進行排序後,您希望迭代列表並檢查它不僅與下一個元素不同,而且還沒有其他相同的元素。考慮列表[3,3,3,5,5]
如果你只會檢查下一個元素,最後的3
也將是唯一的,這是不正確的。
這是一個工作程序,我也使用了一個計數器來覆蓋上述情況。請參閱使用[H|T]
來遍歷列表的語法。你可能會看到更多的案例,並閱讀更多關於它的文章here。
-module(test).
-export([remove_unique/1]).
remove_unique(Input) ->
Sorted = lists:sort(Input),
remove_unique(Sorted, [], 0).
% Base case - checks if element is unique
remove_unique([H|[]],Output,Count) ->
case Count of
0 -> Output;
_Other -> [H|Output]
end;
% Count is 0 - might be unique - check with next element
remove_unique([H1|[H2|T]],Output, 0)->
case (H1 =:= H2) of
true -> remove_unique([H2|T],[H1|Output],1);
false -> remove_unique([H2|T],Output,0)
end;
% Count is > 0 - not unique - proceed adding to list until next value
remove_unique([H1|[H2|T]],Output,Count) ->
case (H1 =:= H2) of
true -> remove_unique([H2|T],[H1|Output],Count+1);
false -> remove_unique([H2|T],[H1|Output],0)
end.
測試
7> test:remove_unique([1,2,3,3,3,5,5,6,7,7]).
[7,7,5,5,3,3,3]
8> test:remove_unique([1,2,3,3,3,5,5,6,7,8]).
[5,5,3,3,3]
謝謝你的幫助! –
無論如何不干擾列表的順序而不使用排序? –
是的,只是迭代相同的方式,每次檢查元素是否再次出現在列表中。如果確實如此 - 將其添加到輸出列表中,否則 - 不要添加。 –
multiple(L) ->
M = L -- lists:usort(L),
[X || X <- L , lists:member(X,M)].
不錯的解決方案,但有一個缺陷,O(n^2)的複雜性。 –
我知道,沒有任何關於列表的典型長度的說明,這個解決方案在PC上可以達到250個元素,使用map的過濾器變得越來越高效。 – Pascal
其實,你的解決方案非常聰明,它如何使用盡可能多的Bifs,這使得短列表非常快。 –
這裏是先看到問題的時候貼的時候我會寫一個解決方案,即使用相同的邏輯@ A.Sarid的遞歸/模式匹配的答案,除了我使用「最後」參數而不是計數。
-module(only_dupes).
-export([process/1]).
process([]) -> [];
process(L) when is_list(L) ->
[H|T] = lists:sort(L),
lists:sort(process(undefined, H, T, [])).
process(Last, Curr, [], Acc)
when Curr =/= Last ->
Acc;
process(_Last, Curr, [], Acc) ->
[Curr | Acc];
process(Last, Curr, [Next | Rest], Acc)
when Curr =/= Last, Curr =/= Next ->
process(Curr, Next, Rest, Acc);
process(_Last, Curr, [Next | Rest], Acc) ->
process(Curr, Next, Rest, [Curr | Acc]).
感謝您的最佳解決方案@Hynek –
使用地圖的非常好的和簡化的解決方案。出於好奇,'map:get'的時間複雜度是多少? –
@ A.Sarid:O(1)通過理論,但O(logN)在實踐中。我還沒有聽說過或看到過技術可以讓O(1)存取時間用於真正未綁定的K/V存儲器,包括存儲器或存儲器本身的線性尋址陣列,但爲什麼會這麼長時間。因此,如果您考慮真正無約束的解決方案,則此解決方案爲O(N * logN)。 –