Массив объектов, преобразовывающих в Set, затем обратно в Array объектов [duplicate]

$name = 'test';
$singleQuote = 'This is example for single quote $name'; // here $name variable not evaluating 
echo $singleQuote; // Output: This is example for single quote $name
$singleQuote = "This is example for single quote $name"; // here $name variable will evaluate and replace variable value
echo $singleQuote; // Output: This is example for single quote test

Also inside single quote expression evaluate faster campare to double quotes
173
задан RB. 26 August 2014 в 12:46
поделиться

25 ответов

Если бы это был PHP, я бы построил массив с ключами и взял array_keys в конце, но JS не имеет такой роскоши. Вместо этого попробуйте следующее:

var flags = [], output = [], l = array.length, i;
for( i=0; i<l; i++) {
    if( flags[array[i].age]) continue;
    flags[array[i].age] = true;
    output.push(array[i].age);
}
79
ответ дан Niet the Dark Absol 27 August 2018 в 05:22
поделиться

с использованием d3.js v3 :

  ages = d3.set(
    array.map(function (d) { return d.age; })
  ).values();
0
ответ дан alex.rind 27 August 2018 в 05:22
поделиться

Я думаю, что вы ищете функцию GroupBy (используя Lodash)

_personsList = [{"name":"Joe", "age":17}, 
                {"name":"Bob", "age":17}, 
                {"name":"Carl", "age": 35}];
_uniqAgeList = _.groupBy(_personsList,"age");
_uniqAges = Object.keys(_uniqAgeList);

создает результат:

17,35

jsFiddle demo: http: // jsfiddle. сеть / 4J2SX / 201 /

3
ответ дан Amil Sajeev 27 August 2018 в 05:22
поделиться

Вот еще один способ решить это:

var result = {};
for(var i in array) {
    result[array[i].age] = null;
}
result = Object.keys(result);

Я понятия не имею, насколько быстро это решение сравнивается с другими, но мне нравится более чистый вид. ;-)


EDIT: Хорошо, это, кажется, самое медленное решение для всех здесь.

Я создал здесь тест производительности: http://jsperf.com/distinct-values-from-array

Вместо тестирования для (Целые числа), я решил сравнить имена (строки).

Метод 1 (решение TS) выполняется очень быстро. Интересно, что метод 7 превосходит все другие решения, здесь я просто избавился от .indexOf () и использовал его «ручную» реализацию, избегая циклической функции вызова:

var result = [];
loop1: for (var i = 0; i < array.length; i++) {
    var name = array[i].name;
    for (var i2 = 0; i2 < result.length; i2++) {
        if (result[i2] == name) {
            continue loop1;
        }
    }
    result.push(name);
}

Разница в производительности с использованием Safari & amp; Firefox поражает, и кажется, что Chrome делает лучшую работу по оптимизации.

Я не совсем уверен, почему приведенные выше фрагменты настолько быстра по сравнению с остальными, может быть, у кого-то мудрее, чем у меня есть ответ. ; -)

7
ответ дан BaM 27 August 2018 в 05:22
поделиться

Если вы, как я, вы предпочитаете более «функциональный» без компрометирующей скорости, в этом примере используется быстрый поиск в словаре, завернутый внутри сокращения.

var array = 
[
    {"name":"Joe", "age":17}, 
    {"name":"Bob", "age":17}, 
    {"name":"Carl", "age": 35}
]
var uniqueAges = array.reduce((p,c,i,a) => {
    if(!p[0][c.age]) {
        p[1].push(p[0][c.age] = c.age);
    }
    if(i<a.length-1) {
        return p
    } else {
        return p[1]
    }
}, [{},[]])

Согласно этому тесту мой решение в два раза быстрее, чем предлагаемый ответ

2
ответ дан bmaggi 27 August 2018 в 05:22
поделиться

Если вы используете ES6 / ES2015 или новее, вы можете сделать это следующим образом:

const unique = [...new Set(array.map(item => item.age))];

Здесь - пример того, как это сделать.

239
ответ дан Casimir 27 August 2018 в 05:22
поделиться

так вы решите это, используя новый Set через ES6 для машинописного текста от 25 августа 2017 года

Array.from(new Set(yourArray.map((item: any) => item.id)))
26
ответ дан Christian Matthew 27 August 2018 в 05:22
поделиться

мои две цента на эту функцию:

var result = [];
for (var len = array.length, i = 0; i < len; ++i) {
  var age = array[i].age;
  if (result.indexOf(age) > -1) continue;
  result.push(age);
}

Вы можете увидеть результат здесь (метод 8) http://jsperf.com/distinct-values-from-array/3

0
ответ дан Dementic 27 August 2018 в 05:22
поделиться
unique(obj, prop) {
    let result = [];
    let seen = new Set();

    Object.keys(obj)
        .forEach((key) => {
            let value = obj[key];

            let test = !prop
                ? value
                : value[prop];

            !seen.has(test)
                && seen.add(test)
                && result.push(value);
        });

    return result;
}
0
ответ дан Devonte 27 August 2018 в 05:22
поделиться
function get_unique_values_from_array_object(array,property){
    var unique = {};
    var distinct = [];
    for( var i in array ){
       if( typeof(unique[array[i][property]]) == "undefined"){
          distinct.push(array[i]);
       }
       unique[array[i][property]] = 0;
    }
    return distinct;
}
4
ответ дан Dmitriy Kupriyanov 27 August 2018 в 05:22
поделиться

Я начал вставлять Underscore во все новые проекты по умолчанию, так что мне никогда не нужно думать об этих проблемах с небольшим количеством данных.

var array = [{"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35}];
console.log(_.chain(array).map(function(item) { return item.age }).uniq().value());

Производит [17, 35].

12
ответ дан Eevee 27 August 2018 в 05:22
поделиться

Я просто сопоставлял и удалял dups:

var ages = array.map(function(obj) { return obj.age; });
ages = ages.filter(function(v,i) { return ages.indexOf(v) == i; });

console.log(ages); //=> [17, 35]

Edit: Aight! Не самый эффективный способ с точки зрения производительности, а самый простой и читаемый IMO. Если вы действительно заботитесь о микро-оптимизации или у вас есть огромное количество данных, то регулярный цикл for будет более «эффективным».

47
ответ дан elclanrs 27 August 2018 в 05:22
поделиться

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

function uniqueBy(arr, prop){
  return arr.reduce((a, d) => {
    if (!a.includes(d[prop])) a.push(d[prop]);
    return a;
  }, []);
}

Используйте его так:

var array = [
  {"name": "Joe", "age": 17}, 
  {"name": "Bob", "age": 17}, 
  {"name": "Carl", "age": 35}
];

var ages = uniqueBy(array, "age");
console.log(ages); // [17, 35]
1
ответ дан Harry Stevens 27 August 2018 в 05:22
поделиться

Использование новых функций Ecma замечательно, но не у всех пользователей есть все доступные.

Следующий код добавит новую функцию с именем, отличной от объекта Global Array. Если вы пытаетесь получить различные значения массива объектов, вы можете передать имя значения, чтобы получить различные значения этого типа.

Array.prototype.distinct = function(item){   var results = [];
for (var i = 0, l = this.length; i < l; i++)
    if (!item){
        if (results.indexOf(this[i]) === -1)
            results.push(this[i]);
        } else {
        if (results.indexOf(this[i][item]) === -1)
            results.push(this[i][item]);
    }
return results;};

Зайдите в мой пост в CodePen для демонстрации.

0
ответ дан Hasan Savran 27 August 2018 в 05:22
поделиться

с использованием lodash

var array = [
    { "name": "Joe", "age": 17 },
    { "name": "Bob", "age": 17 },
    { "name": "Carl", "age": 35 }
];
_.chain(array).pluck('age').unique().value();
> [17, 35]
65
ответ дан Ivan Nosov 27 August 2018 в 05:22
поделиться

Используя функции ES6, вы можете сделать что-то вроде:

const uniqueAges = [...new Set( array.map(obj => obj.age)) ];
33
ответ дан Jon Catmull 27 August 2018 в 05:22
поделиться

эта функция может иметь уникальный массив и объект

function oaunic(x,n=0){
    if(n==0) n = "elem";
    else n = "elem."+n;
    var uval = [];
    var unic = x.filter(function(elem, index, self){
        if(uval.indexOf(eval(n)) < 0){
            uval.push(eval(n));
            return index == self.indexOf(elem);
        }
    })
    return unic;
}

использовать это, как это

tags_obj = [{name:"milad"},{name:"maziar"},{name:"maziar"}]
tags_arr = ["milad","maziar","maziar"]
console.log(oaunic(tags_obj,"name")) //for object
console.log(oaunic(tags_arr)) //for array
0
ответ дан milad 27 August 2018 в 05:22
поделиться

Ответ на forEach ответа @ travis-j (полезен для современных браузеров и Node JS world):

var unique = {};
var distinct = [];
array.forEach(function (x) {
  if (!unique[x.age]) {
    distinct.push(x.age);
    unique[x.age] = true;
  }
});

34% быстрее в Chrome v29.0.1547: http: / /jsperf.com/filter-versus-dictionary/3

И общее решение, которое принимает функцию сопоставления (медленнее, чем прямая карта, но это ожидается):

function uniqueBy(arr, fn) {
  var unique = {};
  var distinct = [];
  arr.forEach(function (x) {
    var key = fn(x);
    if (!unique[key]) {
      distinct.push(key);
      unique[key] = true;
    }
  });
  return distinct;
}

// usage
uniqueBy(array, function(x){return x.age;}); // outputs [17, 35]
17
ответ дан Mrchief 27 August 2018 в 05:22
поделиться

Просто попробуйте

var x = [] ;
for (var i = 0 ; i < array.length ; i++)
{
 if(x.indexOf(array[i]['age']) == -1)
  {
    x.push(array[i]['age']);
  }
}
console.log(x);
0
ответ дан Pravin Pareek 27 August 2018 в 05:22
поделиться

Если у вас есть Array.prototype.includes или готовы polyfill , это работает:

var ages = []; array.forEach(function(x) { if (!ages.includes(x.age)) ages.push(x.age); });
2
ответ дан quillbreaker 27 August 2018 в 05:22
поделиться

underscore.js _.uniq(_.pluck(array,"age"))

6
ответ дан Radosław Kopczyński 27 August 2018 в 05:22
поделиться

Просто нашел это, и я подумал, что это полезно

_.map(_.indexBy(records, '_id'), function(obj){return obj})

Снова используя underscore , поэтому, если у вас есть такой объект

var records = [{_id:1,name:'one', _id:2,name:'two', _id:1,name:'one'}]

он даст вам уникальные объекты.

Что здесь происходит, так это то, что indexBy возвращает такую ​​же карту

{ 1:{_id:1,name:'one'}, 2:{_id:2,name:'two'} }

, и только потому, что это карта, все ключи уникальны .

Затем я просто сопоставляю этот список с массивом.

Если вам нужны только отдельные значения

_.map(_.indexBy(records, '_id'), function(obj,key){return key})

Имейте в виду, что key возвращается как строка, поэтому, если вам нужны целые числа, вы должны сделать

_.map(_.indexBy(records, '_id'), function(obj,key){return parseInt(key)})
2
ответ дан simo 27 August 2018 в 05:22
поделиться

Это универсальное решение, которое использует сокращение, позволяет отображать и поддерживает порядок вставки.

items : массив

mapper : Унарная функция, которая отображает элемент в критерии, или пустая для отображения самого элемента.

function distinct(items, mapper) {
    if (!mapper) mapper = (item)=>item;
    return items.map(mapper).reduce((acc, item) => {
        if (acc.indexOf(item) === -1) acc.push(item);
        return acc;
    }, []);
}

Использование

const distinctLastNames = distinct(items, (item)=>item.lastName);
const distinctItems = distinct(items);

Вы можете добавить это в свой Array prototype и оставить параметр items , если это ваш стиль ...

const distinctLastNames = items.distinct( (item)=>item.lastName) ) ;
const distinctItems = items.distinct() ;

Вы также можете использовать набор вместо массива для ускорения сопоставления.

function distinct(items, mapper) {
    if (!mapper) mapper = (item)=>item;
    return items.map(mapper).reduce((acc, item) => {
        acc.add(item);
        return acc;
    }, new Set());
}
1
ответ дан Steven Spungin 27 August 2018 в 05:22
поделиться

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

var unique = {};
var distinct = [];
for( var i in array ){
 if( typeof(unique[array[i].age]) == "undefined"){
  distinct.push(array[i].age);
 }
 unique[array[i].age] = 0;
}

Вот рабочая демонстрация: http://jsfiddle.net/jbUKP/1

Это будет O (n), где n - количество объектов в массиве, а m - количество уникальных значений. Существует не более быстрый способ, чем O (n), потому что вы должны проверять каждое значение хотя бы один раз.

Производительность

http://jsperf.com/filter-versus- dictionary Когда я запускал этот словарь, он был на 30% быстрее.

92
ответ дан Travis J 27 August 2018 в 05:22
поделиться

Использование Lodash

var array = [
    { "name": "Joe", "age": 17 },
    { "name": "Bob", "age": 17 },
    { "name": "Carl", "age": 35 }
];

_.chain(array).map('age').unique().value();

Возвращает [17,35]

4
ответ дан Yash Vekaria 27 August 2018 в 05:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: