Как уменьшить массив строк javascript до уникальных значений, но сохранить количество дубликатов?

У меня есть массив с несколькими строками, например этот:

["e", "e", "e", "e", "a", "e", "e", "a", "e", "e", "e", "e", "e", "o", "a", "e", "r", "e", "e", "e", "o", "e", "u"]

Теперь я хочу уменьшить этот массив, чтобы он содержал только уникальные строки. В то же время я хочу вести подсчет количества дубликатов и (предпочтительно) вычислять процент, который показывает количество дубликатов, деленное на общее количество строк.

Я думаю, что конечный результат выглядит примерно так:

[
    {
        letter: "e",
        duplicates: 16,
        percentage: 0.695652173913043
    },
    {
        letter: "a",
        duplicates: 3,
        percentage: 0.130434782608696
    },
    {
        letter: "o",
        duplicates: 2,
        percentage: 0.08695652173913
    },
    {
        letter: "r"
        duplicates: 1,
        percentage: 0.043478260869565
    },
    {
        letter: "u",
        duplicates: 1,
        percentage: 0.043478260869565
    }
]

Как мне сделать это преобразование в JavaScript/ES6?

И что вы пробовали для этого, похожего на школьное задание, требующее ответа?

Peter B 15.12.2020 14:29

Это не школьное задание (мне скоро исполнится 50). Это часть лингвистического эксперимента, над которым я работаю. Кроме того, это забавная задача, и я подумал, что сообщество StackOverflow оценит ее. Я знал, что у меня есть и что я хочу получить, мне просто нужна была помощь, чтобы добраться туда.

tkahn 15.12.2020 14:50
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
3
537
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это возможно с помощью Array#from , Array#reduce , Map , Array#map и деструктурирования.

Уменьшение позволяет перегруппировать и подсчитать буквы и их появление. После того, как они были организованы должным образом, вы можете перейти к отображению всех результатов и вычислить процентное соотношение.

const data = ["e", "e", "e", "e", "a", "e", "e", "a", "e", "e", "e", "e", "e", "o", "a", "e", "r", "e", "e", "e", "o", "e", "u"];

const res = Array
  .from(data.reduce((acc, cur) => acc.set(cur, (acc.get(cur)||0) + 1), new Map()))
  .map(([letter, duplicates]) => ({letter, duplicates, percentage: duplicates / data.length}));
  
 console.info(res);

Большое спасибо! Там довольно много всего происходит, поэтому мне понадобится некоторое время, чтобы прочитать это, чтобы понять все, что происходит, но это работает как шарм!

tkahn 15.12.2020 14:46

@tkahn np, если вам нужна более подробная версия, дайте мне знать. Это сжато до максимума.

kemicofa ghost 15.12.2020 14:47
Array.from принимает аргумент отображения, т. е. Array.from(data.reduce(...), ([ letter, duplicates ]) => ...) сделает то же самое за половину итераций.
Mulan 15.12.2020 20:29

@Спасибо за совет, однако я не верю, что это сокращает количество итераций вдвое. «Более ясно, Array.from(obj, mapFn, thisArg) имеет тот же результат, что и Array.from(obj).map(mapFn, thisArg), за исключением того, что он не создает промежуточный массив».

kemicofa ghost 15.12.2020 22:41

Это сокращает количество итераций вдвое, поскольку Array.from выполняет первый проход по записям карты, создает промежуточный массив, затем Array#map выполняет второй проход по промежуточному массиву, создавая второй массив. Array.from(myMap, mappingFn) делает все это за один проход.

Mulan 15.12.2020 22:43

Да, применение карты после Array.from создает промежуточный массив, но не означает ли это, что это удваивает количество итераций? Логически параметр Array.from func должен применяться только после того, как Map будет правильно преобразован в массив внутри.

kemicofa ghost 16.12.2020 00:04

let array = ["e", "e", "e", "e", "a", "e", "e", "a", "e", "e", "e", "e", "e", "o", "a", "e", "r", "e", "e", "e", "o", "e", "u"]


let result = [...new Set(array)].map(e =>({letter:e,
duplicates:array.filter(n => n===e).length,
percentage:array.filter(n => n===e).length/array.length}))


console.info(result)

Спасибо! Это тоже очень хорошее решение моей проблемы! Я вижу, вы использовали синтаксис распространения вместе с Set, с которым я экспериментировал, хотя я так далеко и не продвинулся.

tkahn 15.12.2020 14:53

@tkahn на самом деле это расточительное использование спреда, потому что он создает промежуточный массив только для того, чтобы вызвать на нем .map, что создает другой массив. Array.from(new Set(array), e => ...) правильно писать [...new Set(array)].map(e => ...)

Mulan 15.12.2020 20:32

Другие вопросы по теме