Найти одинаковые элементы в массиве

garphild

Постоялец
Регистрация
19 Май 2009
Сообщения
60
Реакции
31
Есть не менее быстрый вариант с использованием той же идеи что в моем примере, но с использованием новых фишек языка. Стало более читабельно даже.
Код:
var array = [];
var limit = 10000;
function getRandom(limit) {
  return Math.floor(Math.random() * Math.floor(limit));
}
for(var i=0; i<limit; i++){
  array.push(String(getRandom(limit)));
}

var time = new Date().getTime();
array.reduce((agg,col) => {
  agg.filter[col] = agg.filter[col]? agg.dup.push(col): 2;
  return agg
},
{filter:{},dup:[]})
.dup;
console.log(new Date().getTime() - time); // 2
Есть еще варианты на других библиотеках. Например lodash.
Код:
var array = [];
var limit = 10000;
function getRandom(limit) {
  return Math.floor(Math.random() * Math.floor(limit));
}
for(var i=0; i<limit; i++){
  array.push(String(getRandom(limit)));
}

var time = new Date().getTime();
const dup = _(array)
    .countBy()
    .reduce((acc, val, key) => val > 1 ? acc.concat(key) : acc, [])
    .map(_.toNumber)

// console.log(dup);
console.log(new Date().getTime() - time); // 43

Код:
var array = [];
var limit = 10000;
function getRandom(limit) {
  return Math.floor(Math.random() * Math.floor(limit));
}
for(var i=0; i<limit; i++){
  array.push(String(getRandom(limit)));
}
var time = new Date().getTime();
function getDuplicate(array){
  var doubles = {};
  array.forEach((v) => doubles[v] = doubles[v] ? doubles[v] + 1 : 1);
  doubles = Object.keys(doubles).filter((v) => doubles[v] > 1);
  return doubles;
}
getDuplicate(array);
console.log(new Date().getTime() - time); // 2

Код:
var array = [];
var limit = 10000;
function getRandom(limit) {
  return Math.floor(Math.random() * Math.floor(limit));
}
for(var i=0; i<limit; i++){
  array.push(String(getRandom(limit)));
}

var time = new Date().getTime();
var groupped = _.groupBy(array, function (n) {return n});
var result = _.uniq(_.flatten(_.filter(groupped, function (n) {return n.length > 1})));
console.log(new Date().getTime() - time); // 10

Код:
var array = [];
var limit = 10000;
function getRandom(limit) {
  return Math.floor(Math.random() * Math.floor(limit));
}
for(var i=0; i<limit; i++){
  array.push(String(getRandom(limit)));
}

var time = new Date().getTime();
_(array).groupBy().pickBy(x => x.length > 1).keys().value()
console.log(new Date().getTime() - time); // 7
 

sempais8

Писатель
Регистрация
18 Окт 2015
Сообщения
8
Реакции
8
2 garphild
Хорошо, что есть необходимые знания, а фишки языка и библиотеки, это всего лишь инструмент!
 

Absolute

Крокодил ;)
Регистрация
9 Авг 2009
Сообщения
581
Реакции
453
Есть не менее быстрый вариант с использованием той же идеи что в моем примере, но с использованием новых фишек языка. Стало более читабельно даже.
Код:
var array = [];
var limit = 10000;
function getRandom(limit) {
  return Math.floor(Math.random() * Math.floor(limit));
}
for(var i=0; i<limit; i++){
  array.push(String(getRandom(limit)));
}

var time = new Date().getTime();
array.reduce((agg,col) => {
  agg.filter[col] = agg.filter[col]? agg.dup.push(col): 2;
  return agg
},
{filter:{},dup:[]})
.dup;
console.log(new Date().getTime() - time); // 2
c reduce - намудрили))
Например, на массиве ТС будут дубли и всё равно приходим к дополнительному циклу.
Код:
var array = ['Весна', 'Осень', 'Зима', 'Зима', 'Лето', 'Зима', 'Осень'];

var result = array.reduce((agg,col) => {
  agg.filter[col] = agg.filter[col]? agg.dup.push(col): 2;
  return agg
},
{filter:{},dup:[]})
.dup;


console.log(result); //["Зима", "Зима", "Осень"]

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

garphild

Постоялец
Регистрация
19 Май 2009
Сообщения
60
Реакции
31
c reduce - намудрили))
Например, на массиве ТС будут дубли и всё равно приходим к дополнительному циклу.
Код:
var array = ['Весна', 'Осень', 'Зима', 'Зима', 'Лето', 'Зима', 'Осень'];

var result = array.reduce((agg,col) => {
  agg.filter[col] = agg.filter[col]? agg.dup.push(col): 2;
  return agg
},
{filter:{},dup:[]})
.dup;


console.log(result); //["Зима", "Зима", "Осень"]

PS: в подобных тестах от производительности среды запуска и конкретной машины могут результаты различаться для одного и того же кода.

Сгласен. Это чуть перемудрил. Только тогда не к допциклу, а просто к unique. или же к группировке. и по производительности тогда вариант будет отставать. Просто красивый вариант с новыми фишками.
 

Absolute

Крокодил ;)
Регистрация
9 Авг 2009
Сообщения
581
Реакции
453
Только тогда не к допциклу, а просто к unique.
Почти все методы, работающие с массивами - те же циклы внутри.
Просто выполните код:
Код:
console.log($.unique)
И посмотрите как реализован метод в том же jQuery. Не знаю есть этот метод в нативе, но если есть будет плюс/минус похожая реализация, как минимум с одним циклом.
 

garphild

Постоялец
Регистрация
19 Май 2009
Сообщения
60
Реакции
31
Почти все методы, работающие с массивами - те же циклы внутри.
Просто выполните код:
Код:
console.log($.unique)
И посмотрите как реализован метод в том же jQuery. Не знаю есть этот метод в нативе, но если есть будет плюс/минус похожая реализация, как минимум с одним циклом.

По сути да. Я имел в виду дополнительный цикл в самом коде уже внешней программы.
Респект. Вообще мало кто из современных программистов задумывается о том, как работает внутри библиотека. Практически постоянно сталкиваюсь с тем, что люди для выполнения простейшей операции (типа вот этой) тащат в проект целую здоровенную библиотеку и даже не думают о том, что она может быть мягко говоря не оптимальна по производительности. Сейчас ресурс железа стоит меньше времени программиста. Поэтому фраза "да че там, сделал по быстряку. Если что - еще сервер докупим" становится финансово обоснованным возражением на тему "чего твои участки кода так медленно работают" (постарался мягко переформулировать диалог :). Правда если на это посмотреть реально в перспективе, то становится печально.
 

v3w

Писатель
Регистрация
10 Фев 2015
Сообщения
5
Реакции
0
Помогите найти одинаковые элементы в массиве и оставить их в единственном экземпляре, т.е. сделать из этого массива:
Код:
var array = ['Весна', 'Осень', 'Зима', 'Зима', 'Лето', 'Зима', 'Осень']
вот этот:
Код:
var array = ['Осень', 'Зима']
Желателен вариант на jQuery.
Есть же там свойство map потом sort и unique
 

comua

Постоялец
Регистрация
26 Фев 2008
Сообщения
111
Реакции
31
Не совсем в тему, но... в стандарте ES6 есть встроенный объект Для просмотра ссылки Войди или Зарегистрируйся

Но есть пару моментов - поддержка старых браузеров и чувствительность к регистру.

Код:
let arr = ['Весна', 'Осень', 'Зима', 'Зима', 'Лето', 'Зима', 'Осень'];

console.log([...new Set(arr)])

// ["Весна", "Осень", "Зима", "Лето"]

let arrCase = ['Весна', 'Осень', 'зима', 'Зима', 'Лето', 'Зима', 'осень'];

console.log([...new Set(arrCase)]);

// ["Весна", "Осень", "зима", "Зима", "Лето", "осень"]
 

Absolute

Крокодил ;)
Регистрация
9 Авг 2009
Сообщения
581
Реакции
453
Не совсем в тему, но... в стандарте ES6 есть встроенный объект Для просмотра ссылки Войди или Зарегистрируйся
Я пробовал переписывать через Set - работает быстро, но медленнее, чем вариант Для просмотра ссылки Войди или Зарегистрируйся через свойства объектов.
У меня по итогу получился такой код самым быстрым с одним циклом на ES5 для поставленной ТС задачи:
HTML:
function getDuplicate(arr){
    var result = [], temp = {};
    arr.forEach(function(a){
      if (a in temp) {
         if (temp[a]) {
           result.push(a);
           temp[a] = false;
         }
       } else {
         temp[a] = true;
       }
    });
    return result;
}
 
Последнее редактирование:
Сверху