Как получить значение из карты, используя параметр функции в качестве ключа - PullRequest
0 голосов
/ 10 мая 2019
def mapdna(dna) do
  dnarna = %{"G" => "C","C" => "G","T" => "A", "A" => "U"}
  dnarna[dna]
end

Когда я передаю "G" в mapdna, он должен возвращать "C"

Ответы [ 2 ]

1 голос
/ 11 мая 2019

Попробуйте это:

defmodule My do

  def mapdna(dna) 
  when is_binary(dna) do
    %{"G" => "C","C" => "G","T" => "A", "A" => "U"}[dna]
  end

end

#IO.puts My.mapdna(:G)
IO.puts My.mapdna("G")

В elixir, чтобы проверить, является ли аргумент строкой, которую вы используете is_binary/1.

Запуск кода:

$ elixir my.exs
C

Но, если я раскомментирую закомментированную строку:

$ elixir my.exs
** (FunctionClauseError) no function clause matching in My.mapdna/1    

    The following arguments were given to My.mapdna/1:

        # 1
        :G

    my.exs:3: My.mapdna/1
    my.exs:12: (file)
    (elixir) lib/code.ex:677: Code.require_file/2

Ответ на комментарий:

Посмотрите на этот код:

defmodule RNATranscription do 

  @rna_for  %{"G" => "C","C" => "G","T" => "A", "A" => "U"} 

  def to_rna(dna) do  
    String.codepoints(dna)
    |> Enum.map( &(@rna_for[&1]) )
    |> :erlang.list_to_binary
  end 
end

В iex:

~/elixir_programs$ iex my.ex
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)

iex(1)> RNATranscription.to_rna "ACGT" 
"UGCA"

iex(2)> 

Приведенное выше решение не будет очень эффективным для ДЕЙСТВИТЕЛЬНО длинных строк ДНК (оно разбивает строку на список, затем перебирает полученный список, преобразуя значения, а затем обходит список ещеснова объединить все вместе).Для длинных цепочек ДНК вы можете использовать binary pattern matching, чтобы получить каждую букву в цепочке ДНК и построить строку РНК по мере продвижения.Согласно документам erlang для двоичных файлов , следующее решение должно быть высоко оптимизированным способом построения строки РНК - даже если вы добавляете к «хвосту» строки РНК:

defmodule RNATranscription do 

  @rna_for  %{"G" => "C","C" => "G","T" => "A", "A" => "U"} 

  def to_rna(dna) do  
    _to_rna(dna, <<>>)  #The second arg will hold the rna string as it's being built
  end 

  defp _to_rna(<<dna_letter::utf8, rest::binary>>, rna_string) do
    rna_letter = @rna_for[<<dna_letter::utf8>>] 
    _to_rna(rest, <<rna_string::binary, rna_letter::binary>>)
  end
  defp _to_rna(<<>>, rna), do: rna 

end

Обратите внимание, что dna_letter в конечном итоге является кодовой точкой (целое число), и она должна быть преобразована обратно в двоичный файл (строку) с <<....>> для поиска на карте.При сопоставлении двоичных файлов вы не можете использовать шаблон, подобный следующему:

<<dna_letter::binary, rest::binary>>

, поскольку тип ::binary имеет размер по умолчанию, равный «остальной части двоичного файла, который вы пытаетесь сопоставить» (хотяВы можете явно указать размер).В результате, ::binary без размера может появиться только один раз в шаблоне, и это должно быть в конце шаблона.(С другой стороны, размер по умолчанию для ::utf8 - это все байты, составляющие одну кодовую точку utf8, что составляет максимум 4 байта).

Теперь, поскольку все ваши буквы ДНК - это буквы ascii,т. е. всегда длиной 1 байт, вы также можете сопоставить строки ДНК, используя этот шаблон:

<dna_letter::binary-size(1), rest::binary>>

Первый сегмент в шаблоне явно устанавливает размер для типа binary, поэтому он будет соответствовать только одному байтуи dna_letter в конечном итоге будет двоичным (строка), что означает, что вам не придется преобразовывать кодовую строку в строку для поиска на карте.Вот новый шаблон, добавленный к решению:

defmodule RNATranscription do 

  @rna_for  %{"G" => "C","C" => "G","T" => "A", "A" => "U"} 

  def to_rna(dna) do  
    _to_rna(dna, <<>>)  #The second arg will hold the rna string as it's being built
  end 

  defp _to_rna(<<dna_letter::binary-size(1), rest::binary>>, rna_string) do
    rna_letter = @rna_for[dna_letter] 
    _to_rna(rest, <<rna_string::binary, rna_letter::binary>>)
  end
  defp _to_rna(<<>>, rna), do: rna 

end

Интересно, эквивалентна ли строка:

_to_rna(rest, <<acc::binary, rna::binary>>)

:

_to_rna(rest, acc <> rna)

??Если это так, код может использовать еще несколько идиом эликсира:

defmodule RNATranscription do 

  @rna_for  %{"G" => "C","C" => "G","T" => "A", "A" => "U"} 

  def to_rna(dna) do  
    _to_rna(dna, "")  #The second arg will hold the rna string as it's being built
  end 

  defp _to_rna(<<dna_letter::binary-size(1)>> <> rest, rna_string) do
    rna_letter = @rna_for[dna_letter]
    _to_rna(rest, rna_string <> rna_letter)
  end
  defp _to_rna("", rna_string), do: rna_string

end
0 голосов
/ 12 мая 2019

хорошо, нашел ответ

dnarna =% {? G =>? C,? C =>? G,? T =>? A,? A =>? U}

...