Erlang中lists:filter返回"\n\f"而非列表的问题求助
Erlang中lists:filter返回看似字符串的问题解析与修复
首先明确:你看到的"\n\f"不是字符串,而是Erlang Shell对整数列表的自动格式化显示——当列表中的整数恰好对应可打印ASCII字符时,Shell会将其以字符串形式输出。比如10对应换行符\n,12对应换页符\f,所以整数列表[10,12]就会被显示为"\n\f"。你可以用io:format("~p~n", [Result])打印原始列表,就能看到真实的整数内容。
问题根源:add_matching_numbers逻辑偏离需求
你的核心需求是统计每个数字的出现次数是否为偶数,但当前add_matching_numbers函数的逻辑是对连续相同数字求和,而非统计次数:
- 比如测试用例
Test_2的数字列表排序后是[1,2,3,4,5,5,6,6],经过add_matching_numbers处理后得到[10,12](两个5求和为10,两个6求和为12),这两个数恰好是可打印ASCII码,于是Shell显示成了"\n\f"。 - 更关键的是,这个求和逻辑完全无法正确反映数字出现的次数(比如三个相同数字会被拆成两次求和,无法体现次数为奇数)。
修复方案:替换为次数统计逻辑
重新实现统计数字出现次数的函数,再检查所有次数是否为偶数:
-module(challenge). -export([test/0, check_dominos/1]). extract_numbers([]) -> []; extract_numbers([{First, Second} | T]) -> [First, Second | extract_numbers(T)]. % 优化列表拼接,用|代替++更高效 % 统计每个数字的出现次数 count_occurrences(List) -> count_occurrences(lists:sort(List), #{}). count_occurrences([], Map) -> Map; count_occurrences([H|T], Map) -> % 拆分出所有连续相同的数字 {SameGroup, Rest} = lists:splitwith(fun(X) -> X =:= H end, [H|T]), % 记录当前数字的出现次数 count_occurrences(Rest, maps:put(H, length(SameGroup), Map)). check_dominos(Dominos) -> All_Numbers = extract_numbers(Dominos), Occurrence_Map = count_occurrences(All_Numbers), % 检查所有次数是否都是偶数 lists:all(fun(Count) -> Count rem 2 =:= 0 end, maps:values(Occurrence_Map)). test() -> Test_1 = [{1, 3}, {3, 2}, {2, 1}], % Already in order Test_2 = [{5, 2}, {5, 6}, {6, 3}, {1, 4}], % Shouldn't work Test_3 = [{2, 6}, {3, 5}, {1, 4}, {3, 4}, {6, 1}, {2, 5}], % Should work true = check_dominos(Test_1), false = check_dominos(Test_2), true = check_dominos(Test_3).
额外优化点
- 将
[First] ++ [Second] ++ extract_numbers(T)改为[First, Second | extract_numbers(T)],避免不必要的列表拼接,提升效率。 - 使用
maps存储次数统计,比列表更直观易维护。
内容的提问来源于stack exchange,提问作者Skhoooler
相关产品推荐
相关产品推荐

