JavaScript'teki bir nesne dizisinden farklı değerler nasıl alınır?


384

Aşağıdakilere sahip olduğumu varsayarsak:

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

Ne bir sonuç dizisi olsun ki tüm farklı yaşların bir dizi elde edebilmek için en iyi yolu nedir:

[17, 35]

Alternatif olarak ben veri veya daha iyi bir yöntem "yaş" değerini kontrol her dizi üzerinden yinelenmesi ve varlığı için başka bir dizi karşı kontrol ve değilse eklemek zorunda kalmayacak şekilde yapılandırabilir miyim?

Bir şekilde olsaydı, tekrarı olmadan farklı yaşları çıkarabilirdim ...

Mevcut etkisiz bir şekilde geliştirmek istiyorum ... Bunun yerine "dizi" yerine nesnelerin bir dizi olmak, ancak bazı benzersiz anahtar (yani "1,2,3") ile nesnelerin bir "harita" anlamına gelirse tamam da. Sadece en verimli performans yolunu arıyorum.

Şu anda bunu nasıl yapıyorum, ama benim için yineleme işe yarıyor olsa da verimlilik için crummy gibi görünüyor ...

var distinct = []
for (var i = 0; i < array.length; i++)
   if (array[i].age not in distinct)
      distinct.push(array[i].age)

34
yineleme "verimlilik için kırıcı" değildir ve her öğeye "yinelemeden" hiçbir şey yapamazsınız. çeşitli fonksiyonel görünümlü yöntemler kullanabilirsiniz, ancak nihayetinde, bir düzeyde bir şey öğelerin üzerinde tekrar etmelidir.
Eevee

//% 100 çalışan kod const listOfTags = [{id: 1, etiket: "Merhaba", renk: "kırmızı", sıralama: 0}, {id: 2, etiket: "Dünya", renk: "yeşil", sıralama : 1}, {id: 3, etiket: "Merhaba", renk: "mavi", sıralama: 4}, {id: 4, etiket: "Sunshine", renk: "sarı", sıralama: 5}, {id : 5, etiket: "Merhaba", renk: "kırmızı", sıralama: 6}], anahtarlar = ['etiket', 'renk'], filtrelenmiş = listOfTags.filter ((s => o => (k => ! s.has (k) && s.add (k)) (keys.map (k => o [k]). join ('|'))) (yeni Set)); (filtre edilmiş) console.log;
Sandeep Mishra

1
ödül harika, ancak verilen veri ve cevabı olan soru zaten burada cevaplandı: stackoverflow.com/questions/53542882/… . ödülün amacı nedir? Bu soruna iki veya daha fazla anahtarla cevap vermeli miyim?
Nina Scholz

Setnesne ve mapisraftır. Bu iş sadece basit bir .reduce()aşama alıyor.
Redu

Yanıtlar:


126

Bu PHP olsaydı ben tuşları ile bir dizi oluşturmak array_keysve sonunda almak, ama JS böyle lüks yoktur. Bunun yerine şunu deneyin:

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);
}

15
Hayır, çünkü array_uniquesadece burada sorulduğu gibi değil, tüm maddeyi karşılaştırırdı.
Niet the Dark Absol

6
Bence flags = {}daha iyidirflags = []
zhuguowei

3
@zhuguowei belki, seyrek dizilerde gerçekten yanlış bir şey olmamasına rağmen - ve agebunun nispeten küçük bir tamsayı olduğunu varsaydım (<120 elbette)
Niet the Dark Absol

aynı yaştaki toplam insan sayısını nasıl yazdırabiliriz?
user1788736

606

ES6 / ES2015 veya daha yenisini kullanıyorsanız, bunu şu şekilde yapabilirsiniz:

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

İşte bunun nasıl yapılacağıyla ilgili bir örnek.


11
Bir hata alıyorum:TypeError: (intermediate value).slice is not a function
Github'da AngJobs

7
@Thomas ... yayılan operatör anlamına gelir. Bu durumda, yeni küme oluşturmak ve bir listeye yaymak anlamına gelir. Bununla ilgili daha fazla bilgiyi burada bulabilirsiniz: developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Vlad Bezden

10
daktilo için Array.from () içinde sarılmış yeni Set kullanmak zorunda ... ben bu cevabı aşağıda sağlayacaktır. @AngJobs
Christian Matthew

4
nesnedeki birden fazla anahtara dayalı benzersiz nesneler bulmak mümkün müdür?
Jefree Sujit

13
Bu çözüm birkaç ay önce @Russell Vea tarafından neredeyse kelimesi kelimesine verilmiştir. Mevcut cevapları kontrol ettiniz mi? Ama sonra tekrar, 266+ oy başka kimsenin kontrol etmediğini gösteriyor.
Dan Dascalescu

164

ES6 kullanma

let array = [
  { "name": "Joe", "age": 17 },
  { "name": "Bob", "age": 17 },
  { "name": "Carl", "age": 35 }
];
array.map(item => item.age)
  .filter((value, index, self) => self.indexOf(value) === index)

> [17, 35]

2
Eğer değeri diziniyle almak istersem nasıl alabilirim Örnek: {"name": "Bob", "age": "17"}, {"name": "Bob", "age almak istiyorum ":" 17 "}
Abdullah Al Mamun

10
Bu yüzden kaydırmaya devam etmelisin
Alejandro Bastidas

5
@AbdullahAlMamun ilk olarak .map yerine .filter içinde haritayı kullanabilirsiniz, şöyle:array.filter((value, index, self) => self.map(x => x.age).indexOf(value.age) == index)
Leo

1
ps: .map içindeki .filter yavaş olabilir, bu yüzden büyük dizilere dikkat edin
Leo

2
@IvanNosov snippet'iniz çok iyi olmasına rağmen, belgeleri haritalamak ve filtrelemek için işaretçilerle nasıl çalıştığına dair birkaç açıklama satırı, yeni başlayanlar için mükemmel ve net hale getirecektir
azakgaim

128

Bunun gibi bir sözlük yaklaşımı kullanabilirsiniz. Temel olarak "sözlük" te bir anahtar olarak ayırt etmek istediğiniz değeri atarsınız (burada sözlük modundan kaçınmak için nesne olarak bir dizi kullanıyoruz). Anahtar yoksa, bu değeri farklı olarak eklersiniz.

İşte çalışan bir demo:

var array = [{"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35}];
var unique = [];
var distinct = [];
for( let i = 0; i < array.length; i++ ){
  if( !unique[array[i].age]){
    distinct.push(array[i].age);
    unique[array[i].age] = 1;
  }
}
var d = document.getElementById("d");
d.innerHTML = "" + distinct;
<div id="d"></div>

Bu O (n) olacaktır; burada n, dizideki nesnelerin sayısıdır ve m, benzersiz değerlerin sayısıdır. O (n) 'den daha hızlı bir yol yoktur, çünkü her değeri en az bir kez incelemeniz gerekir.

Bunun önceki sürümü bir nesne kullandı ve için. Bunlar doğada küçüktü ve o zamandan beri yukarıda küçük bir şekilde güncellendi. Bununla birlikte, orijinal jsperf'deki iki sürüm arasında performansta ilerlemenin nedeninin nedeni, veri örneği boyutunun çok küçük olmasıydı. Böylece, önceki versiyondaki ana karşılaştırma, dahili harita ve filtre kullanımı ile sözlük modu aramaları arasındaki farka bakıyordu.

Yukarıda belirtildiği gibi yukarıdaki kodu güncelledim, ancak, ben de yerine 3 yerine 1000 nesneleri bakmak için jsperf güncelledik. 3 dahil performans pitfalls ( eski jsperf ) birçok gözden kaçan .

Verim

https://jsperf.com/filter-vs-dictionary-more-data Koştuğumda bu sözlük% 96 daha hızlıydı.

filtreye karşı sözlük


4
hızlı ve ek bir eklenti gerektirmez. Gerçekten harika
mihai

2
nasıl olurif( typeof(unique[array[i].age]) == "undefined"){ distinct.push(array[i].age); unique[array[i].age] = 0; }
Zamansız

7
Vay be performans gerçekten harita seçeneği lehine değişti. O jsperf bağlantısını tıklayın!
AT

1
@ 98percentmonkey - Nesne "sözlük yaklaşımını" kolaylaştırmak için kullanıldı. Nesnenin içine, izlenen her olay bir anahtar (veya bir bölme) olarak eklenir. Bu şekilde, bir olayla karşılaştığımızda, anahtarın (veya çöp kutusunun) var olup olmadığını kontrol edebiliriz; eğer mevcutsa, olayın benzersiz olmadığını biliyoruz - eğer mevcut değilse, olayın benzersiz olduğunu biliyoruz ve ekliyoruz.
Travis J

1
@ 98percentmonkey - Bir nesneyi kullanmanın nedeni, varlığın kontrol edilmesi için her değere bakması gerektiğinden, bir özellik adını bir kez kontrol ettiği için aramanın O (1) olmasıdır. İşlemin sonunda, nesnedeki anahtarlar (kutular) kümesi benzersiz oluşumlar kümesini temsil eder.
Travis J

91

25 Ağustos 2017'den itibaren yeni metin dizesi için ES6 ile yeni Set'i kullanarak bunu nasıl çözersiniz?

Array.from(new Set(yourArray.map((item: any) => item.id)))

3
Bu yardımcı oldu, önce teşekkür almak oldu. 'Set' tipi bir dizi türü değil
Robert

1
Bu harika bir cevap. Bunu aşağı kaydırıncaya kadar, şöyle bir cevap yazacaktım: Object.keys (değerleri. İndirgemek <any> ((x, y) => {x [y] = null; return x;}, {} )); Ancak bu cevap daha özlüdür ve sadece dizeler yerine tüm veri türleri için geçerlidir.
jgosar

1
bu cevap muhteşem!
lukeocodes

78

ES6 özelliklerini kullanarak aşağıdakileri yapabilirsiniz:

const uniqueAges = [...new Set( array.map(obj => obj.age)) ];

6
Bu yaklaşım yalnızca ilkel türler üzerinde çalışacaktır (yaş olarak bir sayı dizisi olduğu için burada olduğu gibi), ancak nesneler için başarısız olacaktır.
k0pernikus

iki anahtarlı nesneler için nasıl çalışacağı hakkında herhangi bir fikir?
cegprakash

1
Gibi bir şeyconst uniqueObjects = [ ...new Set( array.map( obj => obj.age) ) ].map( age=> { return array.find(obj => obj.age === age) } )
Harley B

62

Ben sadece harita ve dups kaldırmak:

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]

Düzenleme: Aight! Performans açısından en etkili yol değil, en basit okunabilir IMO. Mikro optimizasyonu gerçekten önemsiyorsanız veya çok miktarda veriye sahipseniz, düzenli bir fordöngü daha "verimli" olacaktır.


3
@elclanrs - "en etkili performans yolu" - Bu yaklaşım yavaştır .
Travis J

1
@Eevee: Anlıyorum. Cevabınızdaki alt çizgi versiyonu da çok hızlı değil , yani, neyin daha uygun olduğunu seçerseniz,% 1-30'un daha fazla veya daha az genel testlerde ve OP / s binlerce .
elclanrs

4
Eminim. sadece üç element ile , en hızlı şey üç değişken yapmak ve bazı ifs kullanmaktır . üç milyonla çok farklı sonuçlar elde edersiniz.
Eevee

1
hızlı değil ama benim durumumda büyük bir veri kümesiyle uğraşmadığım için hile yaptı, teşekkürler.
Felipe Alarcon

37
var unique = array
    .map(p => p.age)
    .filter((age, index, arr) => arr.indexOf(age) == index)
    .sort(); // sorting is optional

// or in ES6

var unique = [...new Set(array.map(p => p.age))];

// or with lodash

var unique = _.uniq(_.map(array, 'age'));

ES6 örneği

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

const arr = data.map(p => p.age); // [17, 17, 35]
const s = new Set(arr); // {17, 35} a set removes duplications, but it's still a set
const unique = [...s]; // [17, 35] Use the spread operator to transform a set into an Array
// or use Array.from to transform a set into an array
const unique2 = Array.from(s); // [17, 35]

6
Bu kod soruyu cevaplayabilirken, sorunun nasıl ve neden çözüldüğüne dair ek bağlam sağlamak yanıtlayıcının uzun vadeli değerini artıracaktır.
Alexander

İndexOf vs index kullanan ilk sadece parlak.
alas

Bunun yalnızca ilkel değerler için çalıştığını unutmayın. Bir dizi tarihiniz varsa, daha özelleştirilmiş yöntemlere ihtiyacınız vardır. Daha fazla bilgiyi
Molx

36

Anahtarla benzersiz tüm özelliklere sahip nesneyi döndürmek isteyenler için

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

const key = 'age';

const arrayUniqueByKey = [...new Map(array.map(item =>
  [item[key], item])).values()];

console.log(arrayUniqueByKey);

   /*OUTPUT
       [
        { "name": "Bob", "age": 17 },
        { "name": "Carl", "age": 35 }
       ]
   */

 // Note: this will pick the last duplicated item in the list.


2
Not: Bu, listedeki son çoğaltılan öğeyi seçer.
Eugene Kulabuhov

1
Cevaba ekleyerek!
Arun Kumar Saini

1
Tam aradığım şey. Paylaştığın için bir ton teşekkürler!
Devner

1
Dürüst olmak gerekirse bunun en iyi cevap olması gerektiğini düşünüyorum!
Jaroslav Benc

26

Zaten birçok geçerli cevap var, ama reduce()temiz ve basit olduğu için sadece yöntemi kullanan bir tane eklemek istedim .

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

Şöyle kullanın:

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

var ages = uniqueBy(array, "age");
console.log(ages); // [17, 35]

20

forEach(Modern tarayıcılar ve Düğüm JS dünya üzerinde yararlı) @ Travis-j cevap versiyonu:

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

Chrome v29.0.1547'de% 34 daha hızlı: http://jsperf.com/filter-versus-dictionary/3

Eşleyici işlevi alan genel bir çözüm (doğrudan haritadan biraz daha yavaş, ancak bu bekleniyor):

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]

1
Genel çözümü en çok seviyorum çünkü yaşın gerçek dünya senaryosunda ihtiyaç duyulan tek farklı değer olması pek mümkün değil.
Toft

5
Genelde, son derece kullanışlı bulduğum gerçek öğelerin bir listesini döndürmek için "differentt.push (key)" ifadesini "differentt.push (x)" olarak değiştirin!
Silas Hansen

15

Ben yapışmasını başladım alt çizgi Ben bu küçük veri munging problemler hakkında düşünmek zorunda asla sadece bu yüzden varsayılan olarak tüm yeni projelerde.

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());

Üretir [17, 35].


13

İşte bunu çözmenin başka bir yolu:

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

Bu çözümün diğerleriyle ne kadar hızlı karşılaştırıldığına dair hiçbir fikrim yok, ancak daha temiz görünümü beğendim. ;-)


EDIT: Tamam, yukarıdaki tüm burada en yavaş çözüm gibi görünüyor.

Burada bir performans testi örneği oluşturdum: http://jsperf.com/distinct-values-from-array

Yaşları test etmek yerine (Tamsayılar), isimleri karşılaştırmayı seçtim (Dizeler).

Yöntem 1 (TS'nin çözümü) çok hızlıdır. İlginçtir, Yöntem 7 diğer tüm çözümlerden daha iyi performans gösterir, burada sadece .indexOf () 'den kurtuldum ve döngüsel işlev çağrısından kaçınarak "manuel" bir uygulama kullandım:

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 ve Firefox kullanarak performans farkı şaşırtıcı ve Chrome'un optimizasyonda en iyi işi yaptığı görülüyor.

Yukarıdaki snippet'lerin diğerlerine kıyasla neden bu kadar hızlı olduğundan emin değilim, belki benden daha akıllı birisinin cevabı var. ;-)


9

lodash kullanmak

var array = [
    { "name": "Joe", "age": 17 },
    { "name": "Bob", "age": 17 },
    { "name": "Carl", "age": 35 }
];
_.chain(array).pluck('age').unique().value();
> [17, 35]

2
Sorunda ima edildiği gibi düz javascript ile bunun nasıl yapılacağını açıklayabilir misiniz?
Ruskin

alt çizgi fonksiyonudur _. zincir
vini

2
ancak pluck () lodash içinde değildir.
Yash Vekaria

1
_.chain (dizi) .map (yaş ') benzersiz () () değerini..; benim için çalıştı.
Yash Vekaria

sürüm 4.0 bazı kırılma değişiklikleri vardı bakın - stackoverflow.com/a/31740263/4050261
Adarsh ​​Madrecha

7

Lodash'ı kullanma

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

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

İade [17,35]


6
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;
}


5

Burada, azaltma kullanan, eşlemeye izin veren ve ekleme sırasını koruyan çok yönlü bir çözüm var.

öğeler : Bir dizi

mapper : Öğeyi ölçütlerle eşleyen, öğenin kendisini eşlemek için boş olan bir işlev.

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;
    }, []);
}

kullanım

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

Bunu Array prototipinize ekleyebilir ve stiliniz buysa items parametresini dışarıda bırakabilirsiniz ...

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

Eşleştirmeyi hızlandırmak için Dizi yerine bir Küme de kullanabilirsiniz.

function distinct(items, mapper) {
    if (!mapper) mapper = (item)=>item;
    return items.map(mapper).reduce((acc, item) => {
        acc.add(item);
        return acc;
    }, new Set());
}

5

const x = [
  {"id":"93","name":"CVAM_NGP_KW"},
  {"id":"94","name":"CVAM_NGP_PB"},
  {"id":"93","name":"CVAM_NGP_KW"},
  {"id":"94","name":"CVAM_NGP_PB"}
].reduce(
  (accumulator, current) => accumulator.some(x => x.id === current.id)? accumulator: [...accumulator, current ], []
)

console.log(x)

/* output 
[ 
  { id: '93', name: 'CVAM_NGP_KW' },
  { id: '94', name: 'CVAM_NGP_PB' } 
]
*/


2
Bu O (n ^ 2) gibi görünüyor
cegprakash

4

Sadece buldum ve yararlı olduğunu düşündüm

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

Yine alt çizgi kullanarak , eğer böyle bir nesneniz varsa

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

size sadece benzersiz nesneler verecektir.

Burada olan şu ki indexByböyle bir harita döndürüyor

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

sadece bir harita olduğu için tüm tuşlar benzersizdir.

Sonra bu listeyi diziye tekrar eşliyorum.

Yalnızca farklı değerlere ihtiyacınız olması durumunda

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

Bunun keybir dize olarak döndürüldüğünü unutmayın, bunun yerine tamsayılara ihtiyacınız varsa

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

4

Bence (Lodash kullanarak) groupBy işlevi için arıyorsunuz

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

sonuç üretir:

17,35

jsFiddle demosu: http://jsfiddle.net/4J2SX/201/


3

Benim gibi, hızdan ödün vermeden daha "işlevsel" bir tercih ederseniz, bu örnek, kapanmayı azaltmak için içine sarılmış hızlı sözlük araması kullanır.

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]
    }
}, [{},[]])

Bu teste göre benim çözümüm önerilen cevaptan iki kat daha hızlı


3
[...new Set([
    { "name": "Joe", "age": 17 },
    { "name": "Bob", "age": 17 },
    { "name": "Carl", "age": 35 }
  ].map(({ age }) => age))]

3

Kodumu az uzunluk ve zaman karmaşıklığı biliyorum ama bu şekilde denedim bu yüzden anlaşılabilir.

Burada prototip tabanlı işlev geliştirmeye çalışıyorum ve kod da değiştirmek.

Burada, farklı benim prototip fonksiyonum.

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

  Array.prototype.Distinct = () => {
    var output = [];
    for (let i = 0; i < array.length; i++) {
      let flag = true;
      for (let j = 0; j < output.length; j++) {
        if (array[i].age == output[j]) {
          flag = false;
          break;
        }
      }
      if (flag)
        output.push(array[i].age);
    }
    return output;
  }
  //Distinct is my own function
  console.log(array.Distinct());
</script>



1

Aşağıdaki kod, yaşın benzersiz dizisini ve yinelenen yaşa sahip olmayan yeni diziyi gösterecek

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

var unique = [];
var tempArr = [];
data.forEach((value, index) => {
    if (unique.indexOf(value.age) === -1) {
        unique.push(value.age);
    } else {
        tempArr.push(index);    
    }
});
tempArr.reverse();
tempArr.forEach(ele => {
    data.splice(ele, 1);
});
console.log('Unique Ages', unique);
console.log('Unique Array', data);```

1

TipScript'te kendi yazdım, Kotlin'inki gibi genel bir durum için Array.distinctBy {}...

function distinctBy<T, U extends string | number>(array: T[], mapFn: (el: T) => U) {
  const uniqueKeys = new Set(array.map(mapFn));
  return array.filter((el) => uniqueKeys.has(mapFn(el)));
}

Nerede Uelbette hashable olduğunu. Nesneler için https://www.npmjs.com/package/es6-json-stable-stringify adresine ihtiyacınız olabilir.


1

Tüm nesnenin benzersiz olması gerektiğinde

const _ = require('lodash');

var objects = [
  { 'x': 1, 'y': 2 },
  { 'y': 1, 'x': 2 },
  { 'x': 2, 'y': 1 },
  { 'x': 1, 'y': 2 }
];

_.uniqWith(objects, _.isEqual);

[Nesne {x: 1, y: 2}, Nesne {x: 2, y: 1}]


downvoter: Downvote neden açıklamak ister misiniz?
cegprakash

1

Bu eski soruyu cevaplamak oldukça anlamsızdır, ancak Javascript'in doğasıyla ilgili basit bir cevap vardır. Javascript'teki nesneler doğal olarak karma tablolardır. Bunu benzersiz anahtarların bir karmasını elde etmek için kullanabiliriz:

var o = {}; array.map(function(v){ o[v.age] = 1; });

Ardından hash değerini bir benzersiz değer dizisine indirgeyebiliriz:

var a2 = []; for (k in o){ a2.push(k); }

Tüm ihtiyacınız olan bu. A2 dizisi yalnızca benzersiz yaşları içerir.


1

Mükemmel performansa sahip basit bir astar. Testlerimdeki ES6 çözümlerinden% 6 daha hızlı .

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

@ Jeb50 Okunması kolay bir çok satır eklemek ister misiniz? Buradaki diğerlerine baktığımda, okunması veya anlaşılması kolay hissetmiyorum. Bence bunu ne yaptığını açıklayan bir fonksiyona yerleştirmek en iyisidir.
Craig

2
Ok fonksiyonları ile: array.map( o => o.age).filter( (v,i,a) => a.indexOf(v)===i). Fonksiyon anahtar sözcüğünü o kadar nadiren kullanıyorum ki gördüğümde iki kez okumak zorundayım 😊
Drenai
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.