如何在Elixir中不使用嵌套comprehensions实现手机按键字母组合?
Elixir实现手机按键字母组合(无嵌套推导版)
需求说明
实现函数接收老式手机按键对应的数字字符串(如"23"),返回所有按顺序拼接的字母组合列表,要求不能使用嵌套列表推导,且支持任意长度的输入数字串(原代码仅支持固定3位数字,通用性不足)。
修正后的实现代码
defmodule KeypadCombinations do # 空输入直接返回空列表,符合常规预期 def letter_combinations(""), do: [] def letter_combinations(text) do # 修正后的标准手机按键映射,修正原代码中8、7、9键的字母错误 keypad = %{ "2" => ["a", "b", "c"], "3" => ["d", "e", "f"], "4" => ["g", "h", "i"], "5" => ["j", "k", "l"], "6" => ["m", "n", "o"], "7" => ["p", "q", "r", "s"], "8" => ["t", "u", "v"], "9" => ["w", "x", "y", "z"] } text |> String.codepoints() |> Enum.filter(&Map.has_key?(keypad, &1)) # 过滤无对应字母的数字(如1、*、#) |> Enum.reduce([""], fn num, current_combinations -> # 单层列表推导,避免嵌套写法,动态拼接组合 for combo <- current_combinations, char <- keypad[num], do: combo <> char end) end end
代码说明
- 边界处理:输入空字符串时直接返回空列表,避免返回无意义的
[""] - 按键映射修正:修正原代码中8键(应为tuv)、7键(漏了s)、9键(漏了y/z)的字母错误,匹配实际老式手机按键布局
- 过滤无效输入:自动过滤没有对应字母的数字,提升鲁棒性
- 核心逻辑:
- 用
Enum.reduce逐步累积组合,初始值[""]为第一次拼接提供基础字符串 - 每次迭代仅使用单层列表推导,将当前所有组合与当前数字的每个字母拼接,生成新的组合列表
- 支持任意长度的输入数字串,不管是2位、3位还是更长
- 用
测试示例
- 调用
KeypadCombinations.letter_combinations("23"),返回:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"] - 调用
KeypadCombinations.letter_combinations("9"),返回:["w", "x", "y", "z"] - 调用
KeypadCombinations.letter_combinations(""),返回[]
为什么不用嵌套推导
原代码的嵌套推导是硬编码固定层数,只能处理特定长度的输入;而本实现用reduce+单层推导的方式,动态适配输入长度,通用性更强,同时完全避免了嵌套列表推导的写法。
内容的提问来源于stack exchange,提问作者IOEnthusiast
相关产品推荐
相关产品推荐

