параметры функции должны работать для строки и юникода

#elixir

#elixir

Вопрос:

Я подсчитываю количество вхождений в строку с помощью

 def count(strand,nucleotide) do
Enum.count(String.graphemes(strand),amp;(amp;1==List.to_string([nucleotide])))

end
  

Это работает нормально, если я передаю strand как «AAA», но терпит неудачу, если я передаю как «AAA», т.е. charlist.

дает мне

** (FunctionClauseError) в строке нет совпадения с предложением функции.Unicode.graphemes/1

Как я могу заставить это работать и для аргумента unicode

Я могу сделать to_string(strand) , чтобы заставить это работать, но поскольку это список символов, почему я не могу сделать просто, так как Enum.count('AAA',amp;(amp;1 == 'A')) он возвращает мне 0

Ответ №1:

Вы сравниваете список с целым числом.

 is_list('A')                                  # true
[65] == 'A'                                   # true
[65, 66] = 'AB'                               # true
[128105, 8205, 128105, 8205, 128103] == '👩‍👩‍👧'  # true      
  

Вы можете, например, сделать

   Enum.count('AAA', fn x ->
    [codepoint] = 'A'
    x == codepoint
  end)
  

Комментарии:

1. Вероятно, вы хотите сопоставить кодовую точку вне анонимной функции. Таким образом, у вас было бы что-то более похожее на это: Enum.count('AAA', amp;(amp;1 == codepoint)) или, если функция может принимать кодовую точку, что-то вроде Enum.count('AAA', amp;(amp;1 == ?A))

Ответ №2:

Вы можете использовать предложения guard для определения предложения, которое обрабатывает двоичные файлы, и предложения, которое обрабатывает чарлисты. Я думаю, было бы разумнее передать нуклеотид в качестве кодовой точки, а не списка символов:

 defmodule CodepointNucleotide do
  def count(strand, nucleotide) when is_binary(strand) do
    count(String.to_charlist(strand), nucleotide)
  end

  def count(strand, nucleotide) when is_list(strand) do
    Enum.count(strand, amp;(amp;1 == nucleotide))
  end
end
  

Использование:

 iex(1)> CodepointNucleotide.count("AAA", ?A)
3
iex(2)> CodepointNucleotide.count("ABA", ?A)
2
iex(3)> CodepointNucleotide.count('AAA', ?A)
3
iex(4)> CodepointNucleotide.count('ABA', ?A)
2
  

Вы также могли бы сделать нуклеотид двоичным:

 defmodule BinaryNucleotide do
  def count(strand, nucleotide) when is_binary(strand) do
    strand
    |> String.graphemes()
    |> Enum.count(amp;(amp;1 == nucleotide))
  end

  def count(strand, <<nucleotide::utf8>>) when is_list(strand) do
    Enum.count(strand, amp;(amp;1 == nucleotide))
  end
end
  

Использование:

 iex(5)> BinaryNucleotide.count("AAA", "A")
3
iex(6)> BinaryNucleotide.count("ABA", "A")
2
iex(7)> BinaryNucleotide.count('AAA', "A")
3
iex(8)> BinaryNucleotide.count('ABA', "A")
2