Привет, читатель, я вернулся с еще одним эпизодом из этой серии, где мы выбираем одну проблему и рассматриваем несколько решений, написанных на разных языках программирования.
Чтобы прочитать две предыдущие статьи, нажмите :
— здесьдля популярных решений
 — и здесь для палиндромарешения
После надлежащего введения давайте сначала разберемся с проблемой. Частоты — это распространенное понятие, используемое в основном в статистике и ее производных, таких как наука о данных и машинное обучение, и в основном оно состоит из группировки значений по количеству, которое они появлялись, например:
если мы хотим рассчитать возраст определенного населения
ages = [12,5,21,48,84,22,21,29,30,12, 21]
Если мы применим функцию частот, мы получим следующие результаты:
frequencies ages | age | amount of people with that age| | 12 | 2 | 5 | 1 | 21 | 3 | 48 | 1 | 84 | 1 | 22 | 1 | 29 | 1 | 30 | 1
Это простой, но довольно эффективный способ рассуждать о ваших данных, поэтому давайте реализуем функцию частот с нуля и сравним несколько решений.
Первое решение
Первое решение — это решение на python, python — это очень простой разработанный язык, и решение кажется очень понятным, просто взглянув на код, вы можете рассуждать о том, что происходит, единственное наблюдение, которое я бы сделал, это то, что решение имеет изменяемые состояния, которые могут вызывают побочные эффекты:
def frequencies(arr):
  freq = {}
  for v in arr:
    if freq.get(v):
      freq[v] = freq[v]+1
      continue
    freq[v] = 1
  return freq
Решение очень минималистично: одна функция, один dict, один цикл и один if, мы зацикливаем массив за время O (n), проверяя, существует ли возраст в freq dict, если нет, мы добавляем его со значением один, потому что мы нашли одного человека с таким возрастом, иначе мы просто получим количество людей и добавим еще одного.
Второе решение
Второе решение — это версия PHP, эта версия также написана на императивном C-подобном интерпретируемом языке, поэтому процесс решения будет очень похожим.
function frequencies($arr) {
   $freq = [];
   foreach ($arr as &$value) {
      if ($freq[$value]) {
          $freq[$value] = $freq[$value]+1;
          continue;
      }
      $freq[$value] = 1;
   }
   return $freq;
}
Как видите, в нем используются те же структуры, что и в решении на Python, за исключением того, что вместо dict массив PHP также работает как тип словаря. Вы также можете заметить, что решение PHP более подробное и не такое красивое из-за некоторые символы «$», «;», «{» и «}».
Кроме того, решение PHP, к сожалению, имеет те же проблемы с изменчивостью, что и решение Python.
Третье решение
Третье решение также представляет собой C-подобный интерпретируемый язык, но в нем используется другой и более функциональный подход. Третье решение написано на JavaScript и выглядит так:
const freq = ls => ls.reduce((acc, elem) => {
    if (acc[elem]) {
      acc[elem] = acc[elem]+1
    } else {
      acc[elem] = 1
    }
    return acc
 }, {})
Наконец, в более функциональном стиле, я был очень доволен решением JavaScript, потому что это было первое неизменяемое решение в этой статье, которое действительно казалось естественным быть неизменяемым с помощью функции сокращения.
Четвертое решение
Четвертое решение — это скомпилированный системный язык, V — это язык, похожий на GO, который использует современный дизайн с автоматическим освобождением, и решение выглядит следующим образом:
fn freq(arr []int) map[int]int {
   mut m := map[int]int{}
    
   for v in arr{
     if m[v] > 0 {
        m[v] = m[v]+1
        continue
     }
     m[v] = 1
   }
   return m
}
V не имеет функции сокращения (после прочтения комментариев в этой статье я узнал, что V имеет эквивалентную функцию сокращения), поэтому нам пришлось использовать подход создания карты/слова и пройти через массив с циклом и если первые два решения, но мне очень понравилось решение V, потому что для типизированного языка лаконичность и простота действительно выдающиеся.
Пятое решение
Последнее решение — единственное, сделанное на функциональном языке, точнее на языке Elixir, который также использует сокращение для получения неизменяемого решения.
defmodule Freq do
   def freq(ls) do
     Enum.reduce(ls, %{}, fn elem, acc -> check_freq(elem, acc) end)
   end
   def check_freq(key, map) do
     value = Map.get(map, key, nil)
     case value do
       nil   -> Map.put_new(map, key, 1)
       _     -> Map.put(map, key, value+1)
     end
   end
end
Основным отличием этого решения является использование сопоставления case и шаблона вместо подхода if и else, а также использование анонимной функции на этапе сокращения.
И это одна проблема, еще пять решений, третий эпизод доставлен, спасибо, что дочитали до сюда, надеюсь увидеть вас в моей следующей статье.
До встречи!
 
                                                                     
                                                                     
                                                                    