Bagaimana cara mendapatkan nilai berbeda dari berbagai objek dalam JavaScript?


385

Dengan asumsi saya memiliki yang berikut ini:

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

Apa cara terbaik untuk bisa mendapatkan array dari semua umur yang berbeda sehingga saya mendapatkan array hasil:

[17, 35]

Apakah ada beberapa cara saya bisa menyusun data atau metode yang lebih baik sehingga saya tidak perlu beralih melalui setiap array memeriksa nilai "usia" dan memeriksa terhadap array lain untuk keberadaannya, dan menambahkannya jika tidak?

Jika ada cara saya bisa menarik usia yang berbeda tanpa iterasi ...

Cara tidak efisien saat ini saya ingin meningkatkan ... Jika itu berarti bahwa alih-alih "array" menjadi array objek, tetapi "peta" objek dengan beberapa kunci unik (yaitu "1,2,3") yang akan menjadi oke juga. Saya hanya mencari cara yang paling efisien kinerja.

Berikut ini adalah bagaimana saya saat ini melakukannya, tetapi bagi saya, iterasi tampaknya hanya payah untuk efisiensi meskipun itu berfungsi ...

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

34
iterasi bukan "payah untuk efisiensi" dan Anda tidak bisa melakukan apa pun untuk setiap elemen "tanpa iterasi". Anda dapat menggunakan berbagai metode yang tampak fungsional, tetapi pada akhirnya, sesuatu pada tingkat tertentu harus beralih pada item.
Eevee

// 100% running code const listOfTags = [{id: 1, label: "Hello", color: "red", sorting: 0}, {id: 2, label: "World", color: "green", sorting : 1}, {id: 3, label: "Hello", warna: "blue", sorting: 4}, {id: 4, label: "Sunshine", warna: "yellow", sorting: 5}, {id : 5, label: "Hello", color: "red", sorting: 6}], keys = ['label', 'color'], difilter = listOfTags.filter ((s => o => (k => ! s.has (k) && s.add (k)) (keys.map (k => o [k]). join ('|'))) (Set baru)); console.log (difilter);
Sandeep Mishra

1
karunia itu bagus, tetapi pertanyaan dengan data dan jawaban yang diberikan sudah dijawab di sini: stackoverflow.com/questions/53542882/… . apa tujuan dari karunia itu? haruskah saya menjawab masalah khusus ini dengan dua atau lebih kunci?
Nina Scholz

Setobjek dan maps boros. Pekerjaan ini hanya membutuhkan .reduce()tahap sederhana .
Redu

Jawaban:


127

Jika ini PHP, saya akan membuat array dengan kunci dan mengambil array_keyspada akhirnya, tetapi JS tidak memiliki kemewahan seperti itu. Alih-alih, coba ini:

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
Tidak, karena array_uniqueakan membandingkan seluruh item, bukan hanya usia seperti yang diminta di sini.
Niet the Dark Absol

6
Saya pikir flags = {}lebih baik daripadaflags = []
zhuguowei

3
@zhuguowei mungkin, meskipun tidak ada yang salah dengan array jarang - dan saya juga berasumsi itu ageadalah integer yang relatif kecil (<120 pasti)
Niet the Dark Absol

bagaimana kita juga bisa mencetak jumlah total orang yang memiliki usia yang sama?
user1788736

607

Jika Anda menggunakan ES6 / ES2015 atau lebih baru, Anda dapat melakukannya dengan cara ini:

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

Berikut adalah contoh cara melakukannya.


11
Saya mendapatkan kesalahan:TypeError: (intermediate value).slice is not a function
AngJobs di Github

7
@ Thomas ... berarti operator penyebaran. Dalam hal ini berarti membuat set baru dan menyebarkannya dalam daftar. Anda dapat menemukannya lebih lanjut di sini: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Vlad Bezden

10
untuk naskah Anda harus menggunakan Set baru yang dibungkus dengan Array.from () ... saya akan memberikan jawaban di bawah ini. @AngJobs
Christian Matthew

4
apakah mungkin untuk menemukan objek unik berdasarkan beberapa kunci pada objek?
Jefree Sujit

14
Solusi ini diberikan hampir kata demi kata beberapa bulan sebelumnya oleh @Russell Vea. Apakah Anda memeriksa jawaban yang ada? Tapi sekali lagi, 266+ suara menunjukkan bahwa tidak ada orang lain yang memeriksa.
Dan Dascalescu

165

menggunakan ES6

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
Jika saya ingin mendapatkan nilai dengan indeksnya maka bagaimana saya bisa mendapatkan Contoh: Saya ingin mendapatkan {"name": "Bob", "age": "17"}, {"name": "Bob", "age ":" 17 "}
Abdullah Al Mamun

10
Itu sebabnya Anda harus terus bergulir
Alejandro Bastidas

5
@AbdullahAlMamun Anda dapat menggunakan peta di .filter alih-alih memanggil .map dulu, seperti ini:array.filter((value, index, self) => self.map(x => x.age).indexOf(value.age) == index)
Leo

1
ps: .map di dalam .filter bisa lambat, jadi hati-hati dengan array besar
Leo

2
@IvanNosov cuplikan Anda sangat bagus meskipun beberapa baris penjelasan cara kerjanya dengan pointer untuk memetakan dan memfilter dokumentasi akan membuatnya sempurna dan jelas untuk pemula
azakgaim

128

Anda bisa menggunakan pendekatan kamus seperti ini. Pada dasarnya Anda menetapkan nilai yang ingin Anda bedakan sebagai kunci dalam "kamus" (di sini kami menggunakan array sebagai objek untuk menghindari mode kamus). Jika kunci tidak ada maka Anda menambahkan nilai itu sebagai berbeda.

Ini demo yang berfungsi:

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>

Ini akan menjadi O (n) di mana n adalah jumlah objek dalam array dan m adalah jumlah nilai unik. Tidak ada cara yang lebih cepat daripada O (n) karena Anda harus memeriksa setiap nilai setidaknya satu kali.

Versi sebelumnya ini menggunakan objek, dan untuk in. Ini sifatnya minor, dan sejak itu sedikit diperbarui di atas. Namun, alasan tampaknya kemajuan dalam kinerja antara dua versi di jsperf asli adalah karena ukuran sampel data yang sangat kecil. Dengan demikian, perbandingan utama dalam versi sebelumnya adalah melihat perbedaan antara peta internal dan penggunaan filter versus pencarian mode kamus.

Saya telah memperbarui kode di atas, sebagaimana dicatat, namun, saya juga memperbarui jsperf untuk melihat melalui 1000 objek, bukan 3. 3 mengabaikan banyak jebakan kinerja yang terlibat ( jsperf usang ).

Performa

https://jsperf.com/filter-vs-dictionary-more-data Ketika saya menjalankan kamus ini 96% lebih cepat.

filter vs kamus


4
cepat, dan tanpa plugin tambahan yang diperlukan. Sangat keren
mihai

2
bagaimanaif( typeof(unique[array[i].age]) == "undefined"){ distinct.push(array[i].age); unique[array[i].age] = 0; }
Timeless

7
Wow kinerjanya telah benar-benar berubah mendukung opsi peta. Klik tautan jsperf itu!
PADA

1
@ 98percentmonkey - Objek digunakan untuk memfasilitasi "pendekatan kamus". Di dalam objek, setiap kejadian yang dilacak ditambahkan sebagai kunci (atau bin). Dengan cara ini, ketika kita menemukan kejadian, kita dapat memeriksa untuk melihat apakah kunci (atau bin) ada; jika memang ada, kita tahu bahwa kejadian itu tidak unik - jika itu tidak ada, kita tahu bahwa kejadian itu unik dan menambahkannya.
Travis J

1
@ 98percentmonkey - Alasan untuk menggunakan objek adalah bahwa pencarian adalah O (1) karena memeriksa nama properti satu kali, sedangkan array adalah O (n) karena harus melihat setiap nilai untuk memeriksa keberadaan. Pada akhir proses, himpunan kunci (nampan) dalam objek mewakili himpunan kejadian unik.
Travis J

91

Ini adalah bagaimana Anda akan menyelesaikan ini menggunakan Set baru melalui ES6 untuk mengeskrip pada 25 Agustus 2017

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

3
ini membantu, mendapatkan sebelum terima kasih. Ketik 'Set' bukan tipe array
robert king

1
Ini jawaban yang bagus. Sampai saya menggulir ke bawah ke yang ini, saya akan menulis jawaban yang mengatakan: Object.keys (values.reduce <any> ((x, y) => {x [y] = null; return x;}, {} )); Tetapi jawaban ini lebih ringkas dan berlaku untuk semua tipe data, bukan hanya string.
jgosar

1
jawaban ini luar biasa!
lukeocodes

79

Menggunakan fitur ES6, Anda dapat melakukan sesuatu seperti:

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

6
Pendekatan ini hanya akan bekerja pada tipe primitif (yang terjadi di sini karena usia adalah array angka) namun akan gagal untuk objek.
k0pernikus

tahu bagaimana membuatnya bekerja untuk objek dengan dua tombol?
cegprakash

1
Sesuatu seperticonst uniqueObjects = [ ...new Set( array.map( obj => obj.age) ) ].map( age=> { return array.find(obj => obj.age === age) } )
Harley B

62

Saya baru saja memetakan dan menghapus 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]

Sunting: Aight! Bukan cara yang paling efisien dalam hal kinerja, tetapi IMO yang paling mudah dibaca. Jika Anda benar-benar peduli tentang optimasi mikro atau Anda memiliki jumlah data yang besar, maka forperulangan reguler akan lebih "efisien".


3
@elclanrs - "cara paling efisien kinerja" - Pendekatan ini lambat .
Travis J

1
@Eevee: Begitu. Versi garis bawah dalam jawaban Anda juga tidak terlalu cepat , maksud saya, pada akhirnya Anda memilih yang lebih nyaman, saya ragu 1-30% lebih atau kurang mencerminkan "peningkatan besar" dalam tes generik dan ketika OP / s berada dalam ribuan .
elclanrs

4
baik, tentu. dengan hanya tiga elemen , hal tercepat adalah membuat tiga variabel dan menggunakan beberapa ifs. Anda akan mendapatkan hasil yang sangat berbeda dengan tiga juta.
Eevee

1
tidak cepat tetapi dalam kasus saya itu berhasil karena saya tidak berurusan dengan dataset besar, terima kasih.
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'));

Contoh ES6

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
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang bagaimana dan mengapa memecahkan masalah akan meningkatkan nilai jangka panjang jawaban.
Alexander

Yang pertama yang menggunakan indexOf vs indeks hanya brilian.
sayangnya

Perhatikan bahwa ini hanya berfungsi untuk nilai primitif. Jika Anda memiliki serangkaian tanggal, maka Anda memerlukan beberapa metode yang lebih khusus. Baca lebih lanjut di sini: codeburst.io/javascript-array-distinct-5edc93501dc4
Molx

36

Bagi mereka yang ingin mengembalikan objek dengan semua properti unik dengan kunci

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
Catatan: ini akan memilih item duplikat terakhir dalam daftar.
Eugene Kulabuhov

1
Menambahkan ini ke jawabannya!
Arun Kumar Saini

1
Persis apa yang saya cari. Terima kasih banyak untuk berbagi!
Devner

1
Saya pikir ini harus menjadi jawaban TOP untuk jujur!
Jaroslav Benc

26

Sudah banyak jawaban yang valid, tetapi saya ingin menambahkan satu yang hanya menggunakan reduce()metode karena bersih dan sederhana.

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

Gunakan seperti ini:

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

The forEachVersi jawaban @ travis-j ini (membantu pada browser modern dan dunia Node JS):

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

34% lebih cepat di Chrome v29.0.1547: http://jsperf.com/filter-versus-dictionary/3

Dan solusi umum yang mengambil fungsi mapper (sedikit lebih lambat dari peta langsung, tapi itu diharapkan):

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
Saya suka solusi generik yang terbaik karena usia tidak mungkin satu-satunya nilai berbeda yang diperlukan dalam skenario dunia nyata.
Toft

5
Dalam generik, ubah "differ.push (kunci)" menjadi "differ.push (x)" untuk mengembalikan daftar elemen aktual, yang menurut saya sangat berguna!
Silas Hansen

15

Saya sudah mulai menempel Garis Bawah di semua proyek baru secara default, jadi saya tidak pernah harus memikirkan masalah kecil data-munging ini.

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

Menghasilkan [17, 35].


13

Berikut cara lain untuk menyelesaikan ini:

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

Saya tidak tahu seberapa cepat solusi ini dibandingkan dengan yang lain, tapi saya suka tampilan yang lebih bersih. ;-)


EDIT: Oke, di atas tampaknya menjadi solusi paling lambat di sini.

Saya telah membuat case test kinerja di sini: http://jsperf.com/distinct-values-from-array

Alih-alih menguji untuk usia (Integer), saya memilih untuk membandingkan nama (Strings).

Metode 1 (solusi TS) sangat cepat. Yang cukup menarik, Metode 7 mengungguli semua solusi lain, di sini saya baru saja menyingkirkan .indexOf () dan menggunakan implementasi "manual", menghindari panggilan fungsi yang berulang:

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

Perbedaan dalam kinerja menggunakan Safari & Firefox adalah luar biasa, dan sepertinya Chrome melakukan pekerjaan terbaik pada optimasi.

Saya tidak begitu yakin mengapa cuplikan di atas sangat cepat dibandingkan dengan yang lain, mungkin seseorang yang lebih bijak dari saya punya jawabannya. ;-)


9

menggunakan lodash

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

2
Bisakah Anda menjelaskan bagaimana melakukan ini dengan javascript biasa seperti yang tersirat dalam pertanyaan?
Ruskin

ini adalah fungsi garis bawah _.chain
vini

2
tapi memetik () tidak ada di lodash.
Yash Vekaria

1
_.chain (array) .map ('usia') .unik () .nilai (); bekerja untukku.
Yash Vekaria

versi 4.0 mengalami beberapa perubahan perubahan merujuk - stackoverflow.com/a/31740263/4050261
Adarsh ​​Madrecha

7

Menggunakan Lodash

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

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

Pengembalian [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

Berikut adalah solusi serbaguna yang menggunakan pengurangan, memungkinkan untuk pemetaan, dan mempertahankan urutan penyisipan.

barang : sebuah array

mapper : Fungsi unary yang memetakan item ke kriteria, atau kosong untuk memetakan item itu sendiri.

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

Pemakaian

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

Anda dapat menambahkan ini ke prototipe Array Anda dan meninggalkan parameter item jika itu gaya Anda ...

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

Anda juga dapat menggunakan Set alih-alih Array untuk mempercepat pencocokan.

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
ini terlihat seperti O (n ^ 2)
cegprakash

4

Baru saja menemukan ini dan saya pikir ini berguna

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

Sekali lagi menggunakan garis bawah , jadi jika Anda memiliki objek seperti ini

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

itu akan memberi Anda objek unik saja.

Apa yang terjadi di sini adalah indexBymengembalikan peta seperti ini

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

dan hanya karena ini peta, semua kunci unik.

Lalu saya hanya memetakan daftar ini kembali ke array.

Jika Anda hanya perlu nilai yang berbeda

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

Perlu diingat bahwa keydikembalikan sebagai string sehingga, jika Anda membutuhkan bilangan bulat, Anda harus melakukannya

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

4

saya pikir Anda mencari fungsi groupBy (menggunakan Lodash)

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

menghasilkan hasil:

17,35

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


3

Jika seperti saya Anda lebih suka yang lebih "fungsional" tanpa mengurangi kecepatan, contoh ini menggunakan kamus cepat yang dibungkus di dalam mengurangi penutupan.

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

Menurut tes ini solusi saya dua kali lebih cepat dari jawaban yang diusulkan


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

3

Saya tahu kode saya sedikit panjang dan sedikit kompleksitas waktu tetapi dapat dimengerti jadi saya mencoba cara ini.

Saya mencoba mengembangkan fungsi berbasis prototipe di sini dan kode juga berubah.

Di sini, Distinct adalah fungsi prototipe saya sendiri.

<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>


2

Jika Anda memiliki Array.prototype.includes atau bersedia untuk mengisinya , ini berfungsi:

var ages = []; array.forEach(function(x) { if (!ages.includes(x.age)) ages.push(x.age); });

1

Kode saya di bawah ini akan menunjukkan array umur yang unik dan juga array baru yang tidak memiliki usia duplikat

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

Saya menulis sendiri di TypeScript, untuk kasus generik, seperti itu di Kotlin 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)));
}

Di mana Uhashable, tentu saja. Untuk Objek, Anda mungkin perlu https://www.npmjs.com/package/es6-json-stable-stringify


1

Jika Anda perlu objek unik yang unik

const _ = require('lodash');

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

_.uniqWith(objects, _.isEqual);

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


downvoter: Pikiran menjelaskan mengapa downvote?
cegprakash

1

Menjawab pertanyaan lama ini tidak ada gunanya, tetapi ada jawaban sederhana yang berbicara tentang sifat Javascript. Objek dalam Javascript pada dasarnya adalah tabel hash. Kita dapat menggunakan ini untuk mendapatkan hash kunci unik:

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

Lalu kita bisa mengurangi hash ke array nilai unik:

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

Itu yang kamu butuhkan. Array a2 hanya berisi usia unik.


1

Satu garis sederhana dengan kinerja luar biasa. 6% lebih cepat dari solusi ES6 dalam pengujian saya .

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

@ Jeb50 Care untuk menambahkan multi-line yang mudah dibaca? Melihat yang lain di sini saya benar-benar merasa tidak mudah dibaca atau dimengerti. Saya pikir yang terbaik adalah menempatkan ini dalam fungsi yang menggambarkan fungsinya.
Craig

2
Dengan fungsi panah: array.map( o => o.age).filter( (v,i,a) => a.indexOf(v)===i). Saya menggunakan fungsi kunci sangat jarang sekarang bahwa saya harus membaca hal-hal dua kali ketika saya melihatnya 😊
Drenai
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.