Когда я внедрял алгоритм Elo Rating несколько недель назад, мне нужно было создать базовый рейтинг для каждой команды.
Я начал с набора команд, которые выглядели так:
(def teams #{ "Man Utd" "Man City" "Arsenal" "Chelsea"})
и я хотел преобразовать это в карту от команды до их рейтинга, например
Man Utd -> {:points 1200} Man City -> {:points 1200} Arsenal -> {:points 1200} Chelsea -> {:points 1200}
Я прочитал документацию по array-map , функции, которую можно использовать для преобразования набора пар в карту, и казалось, что он может сработать.
Я начал с создания массива пар, используя mapcat :
> (mapcat (fn [x] [x {:points 1200}]) teams) ("Chelsea" {:points 1200} "Man City" {:points 1200} "Arsenal" {:points 1200} "Man Utd" {:points 1200})
массив-карта строит карту из пар значений, например
> (array-map "Chelsea" {:points 1200} "Man City" {:points 1200} "Arsenal" {:points 1200} "Man Utd" {:points 1200}) ("Chelsea" {:points 1200} "Man City" {:points 1200} "Arsenal" {:points 1200} "Man Utd" {:points 1200})
Так как у нас есть коллекция пар, а не отдельных пар, нам нужно также использовать функцию apply :
> (apply array-map ["Chelsea" {:points 1200} "Man City" {:points 1200} "Arsenal" {:points 1200} "Man Utd" {:points 1200}]) {"Chelsea" {:points 1200}, "Man City" {:points 1200}, "Arsenal" {:points 1200}, "Man Utd" {:points 1200}}
И если мы соберем все это вместе, мы получим следующее:
> (apply array-map (mapcat (fn [x] [x {:points 1200}]) teams)) {"Man Utd" {:points 1200}, "Man City" {:points 1200}, "Arsenal" {:points 1200}, "Chelsea" {:points 1200}}
Это работает, но функция, которую мы передаем в mapcat, выглядит немного неуклюжей. Так как нам просто нужно создать коллекцию пар команда / рейтинг, мы можем использовать функции вектора и повтора, чтобы создать это вместо:
> (mapcat vector teams (repeat {:points 1200})) ("Chelsea" {:points 1200} "Man City" {:points 1200} "Arsenal" {:points 1200} "Man Utd" {:points 1200})
И если мы вернем код применения массива-карты обратно, мы все равно получим желаемый результат:
> (apply array-map (mapcat vector teams (repeat {:points 1200}))) {"Chelsea" {:points 1200}, "Man City" {:points 1200}, "Arsenal" {:points 1200}, "Man Utd" {:points 1200}}
В качестве альтернативы мы могли бы использовать Assoc следующим образом:
> (apply assoc {} (mapcat vector teams (repeat {:points 1200}))) {"Man Utd" {:points 1200}, "Arsenal" {:points 1200}, "Man City" {:points 1200}, "Chelsea" {:points 1200}}
Я также натолкнулся на функцию, которая казалась полезной, но взял коллекцию векторов:
> (into {} [["Chelsea" {:points 1200}] ["Man City" {:points 1200}] ["Arsenal" {:points 1200}] ["Man Utd" {:points 1200}] ])
Поэтому нам нужно изменить код для использования map вместо mapcat :
> (into {} (map vector teams (repeat {:points 1200}))) {"Chelsea" {:points 1200}, "Man City" {:points 1200}, "Arsenal" {:points 1200}, "Man Utd" {:points 1200}}
Тем не менее, моя любимая версия до сих пор использует функцию zipmap :
> (zipmap teams (repeat {:points 1200})) {"Man Utd" {:points 1200}, "Arsenal" {:points 1200}, "Man City" {:points 1200}, "Chelsea" {:points 1200}}
Я уверен, что есть и другие способы сделать это, поэтому, если вы знаете, сообщите мне в комментариях.