Wie erhalte ich unterschiedliche Werte aus einem Array von Objekten in JavaScript?

384

Angenommen, ich habe Folgendes:

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

Was ist der beste Weg, um ein Array aller unterschiedlichen Altersstufen zu erhalten, sodass ich ein Ergebnis-Array von:

[17, 35]

Gibt es eine Möglichkeit, die Daten oder eine bessere Methode alternativ so zu strukturieren, dass ich nicht jedes Array durchlaufen muss, um den Wert von "age" zu überprüfen und anhand eines anderen Arrays auf seine Existenz zu prüfen und es hinzuzufügen, wenn nicht?

Wenn es eine Möglichkeit gäbe, könnte ich einfach die verschiedenen Zeitalter herausziehen, ohne zu iterieren ...

Derzeit ineffiziente Art und Weise möchte ich verbessern ... Wenn es bedeutet, dass anstelle von "Array" ein Array von Objekten, sondern eine "Karte" von Objekten mit einem eindeutigen Schlüssel (dh "1,2,3") wäre okay auch. Ich bin nur auf der Suche nach dem leistungsstärksten Weg.

Das Folgende ist, wie ich es derzeit mache, aber für mich scheint die Iteration aus Effizienzgründen nur mies zu sein, obwohl sie funktioniert ...

var distinct = []
for (var i = 0; i < array.length; i++)
   if (array[i].age not in distinct)
      distinct.push(array[i].age)
Rolando
quelle
34
Iteration ist nicht "mies für Effizienz" und Sie können nicht mit jedem Element "ohne Iteration" etwas anfangen. Sie können verschiedene funktional aussehende Methoden verwenden, aber letztendlich muss etwas auf einer bestimmten Ebene über die Elemente iterieren.
Eevee
// 100% laufender Code const listOfTags = [{id: 1, Bezeichnung: "Hallo", Farbe: "rot", Sortierung: 0}, {id: 2, Bezeichnung: "Welt", Farbe: "grün", Sortierung : 1}, {id: 3, Bezeichnung: "Hallo", Farbe: "blau", Sortierung: 4}, {id: 4, Bezeichnung: "Sonnenschein", Farbe: "gelb", Sortierung: 5}, {id : 5, Bezeichnung: "Hallo", Farbe: "Rot", Sortierung: 6}], Schlüssel = ['Bezeichnung', 'Farbe'], gefiltert = listOfTags.filter ((s => o => (k =>) ! s.has (k) && s.add (k)) (keys.map (k => o [k]). join ('|'))) (new Set)); console.log (gefiltert);
Sandeep Mishra
1
Das Kopfgeld ist großartig, aber die Frage mit den angegebenen Daten und Antworten wird hier bereits beantwortet: stackoverflow.com/questions/53542882/… . Was ist der Zweck der Prämie? Soll ich dieses spezielle Problem mit zwei oder mehr Schlüsseln beantworten?
Nina Scholz
SetObjekt und maps sind verschwenderisch. Dieser Job dauert nur eine einfache .reduce()Phase.
Reduzieren Sie den

Antworten:

126

Wenn dies PHP wäre, würde ich ein Array mit den Schlüsseln erstellen und array_keysam Ende nehmen, aber JS hat keinen solchen Luxus. Versuchen Sie stattdessen Folgendes:

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);
}
Niet the Dark Absol
quelle
15
Nein, denn array_uniquewürde den gesamten Artikel vergleichen, nicht nur das Alter, wie hier gefragt wird.
Niet the Dark Absol
6
Ich denke, flags = {}ist besser alsflags = []
zhuguowei
3
@zhuguowei vielleicht, obwohl es nichts wirklich Falsches an spärlichen Arrays gibt - und ich nahm auch an, dass dies ageeine relativ kleine ganze Zahl ist (<120 sicher)
Niet the Dark Absol
Wie könnten wir auch die Gesamtzahl der gleichaltrigen Personen ausdrucken?
user1788736
606

Wenn Sie ES6 / ES2015 oder höher verwenden, können Sie dies folgendermaßen tun:

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

Hier ist ein Beispiel dafür.

Vlad Bezden
quelle
11
Ich erhalte eine Fehlermeldung:TypeError: (intermediate value).slice is not a function
AngJobs auf Github
7
@Thomas ... bedeutet Spread-Operator. In diesem Fall bedeutet dies, dass Sie einen neuen Satz erstellen und in einer Liste verteilen. Weitere
Informationen
10
Für Typoskript müssen Sie ein neues Set verwenden, das in Array.from () eingeschlossen ist. Diese Antwort werde ich unten geben. @ AngJobs
Christian Matthew
4
Ist es möglich, eindeutige Objekte anhand mehrerer Schlüssel im Objekt herauszufinden?
Jefree Sujit
13
Diese Lösung wurde einige Monate zuvor von @Russell Vea fast wörtlich gegeben. Haben Sie nach vorhandenen Antworten gesucht? Andererseits zeigen mehr als 266 Stimmen, dass auch sonst niemand nachgesehen hat.
Dan Dascalescu
164

mit 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]
Ivan Nosov
quelle
2
Wenn ich den Wert mit seinem Index erhalten möchte, wie kann ich dann erhalten? Beispiel: Ich möchte {"Name": "Bob", "Alter": "17"}, {"Name": "Bob", "Alter" erhalten ":" 17 "}
Abdullah Al Mamun
10
Deshalb muss man weiter scrollen
Alejandro Bastidas
5
@AbdullahAlMamun Sie können Karte in .filter verwenden, anstatt zuerst .map aufzurufen, wie folgt:array.filter((value, index, self) => self.map(x => x.age).indexOf(value.age) == index)
Leo
1
ps: .map in .filter kann langsam sein, seien Sie also vorsichtig mit großen Arrays
Leo
2
@IvanNosov Ihr Snippet ist sehr gut, obwohl mehrere Erklärungszeilen, wie es mit Zeigern auf Karten- und Filterdokumentation funktioniert, es für Anfänger perfekt und klar machen
Azakgaim
128

Sie könnten einen Wörterbuchansatz wie diesen verwenden. Grundsätzlich weisen Sie den Wert, den Sie als Schlüssel unterscheiden möchten, als "Wörterbuch" zu (hier verwenden wir ein Array als Objekt, um den Wörterbuchmodus zu vermeiden). Wenn der Schlüssel nicht vorhanden war, fügen Sie diesen Wert als eindeutig hinzu.

Hier ist eine funktionierende 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>

Dies ist O (n), wobei n die Anzahl der Objekte im Array und m die Anzahl der eindeutigen Werte ist. Es gibt keinen schnelleren Weg als O (n), da Sie jeden Wert mindestens einmal überprüfen müssen.

In der vorherigen Version wurde ein Objekt und für in verwendet. Diese waren geringfügiger Natur und wurden seitdem oben geringfügig aktualisiert. Der Grund für einen scheinbaren Leistungszuwachs zwischen den beiden Versionen im ursprünglichen jsperf war jedoch, dass die Datenstichprobengröße so klein war. Der Hauptvergleich in der vorherigen Version befasste sich daher mit dem Unterschied zwischen der Verwendung der internen Karte und des Filters im Vergleich zu den Suchvorgängen im Wörterbuchmodus.

Ich habe den obigen Code aktualisiert, wie bereits erwähnt. Ich habe jedoch auch den jsperf aktualisiert, um 1000 statt 3 Objekte zu durchsuchen. 3 hat viele der damit verbundenen Leistungsprobleme übersehen ( veralteter jsperf ).

Performance

https://jsperf.com/filter-vs-dictionary-more-data Als ich dieses Wörterbuch ausführte, war es 96% schneller.

Filter gegen Wörterbuch

Travis J.
quelle
4
schnell und ohne zusätzliche Plugins erforderlich. Wirklich cool
Mihai
2
wie wäre esif( typeof(unique[array[i].age]) == "undefined"){ distinct.push(array[i].age); unique[array[i].age] = 0; }
Timeless
7
Wow, die Leistung hat sich wirklich zugunsten der Kartenoption geändert. Klicken Sie auf diesen jsperf-Link!
AT
1
@ 98percentmonkey - Das Objekt wurde verwendet, um den "Wörterbuchansatz" zu vereinfachen. Innerhalb des Objekts wird jedes verfolgte Vorkommen als Schlüssel (oder Bin) hinzugefügt. Auf diese Weise können wir bei Auftreten eines Ereignisses überprüfen, ob der Schlüssel (oder der Behälter) vorhanden ist. Wenn es existiert, wissen wir, dass das Vorkommen nicht eindeutig ist. Wenn es nicht existiert, wissen wir, dass das Vorkommen eindeutig ist, und fügen es hinzu.
Travis J
1
@ 98percentmonkey - Der Grund für die Verwendung eines Objekts ist, dass die Suche O (1) ist, da einmal nach einem Eigenschaftsnamen gesucht wird, während ein Array O (n) ist, da jeder Wert überprüft werden muss, um die Existenz zu überprüfen. Am Ende des Prozesses repräsentiert der Satz von Schlüsseln (Bins) im Objekt den Satz von eindeutigen Vorkommen.
Travis J
91

So würden Sie dies mit dem neuen Set über ES6 für Typescript ab dem 25. August 2017 lösen

Array.from(new Set(yourArray.map((item: any) => item.id)))
Christian Matthew
quelle
3
das half, wurde vorher danke. Typ 'Set' ist kein Array-Typ
Robert King
1
Dies ist eine großartige Antwort. Bis ich zu diesem gescrollt habe, wollte ich eine Antwort schreiben, die besagt: Object.keys (values.reduce <any> ((x, y) => {x [y] = null; return x;}, {} )); Diese Antwort ist jedoch präziser und gilt für alle Datentypen anstatt nur für Zeichenfolgen.
Jgosar
1
Diese Antwort ist spektakulär!
Lukecodes
78

Mit den ES6-Funktionen können Sie Folgendes tun:

const uniqueAges = [...new Set( array.map(obj => obj.age)) ];
Russell Vea
quelle
6
Dieser Ansatz funktioniert nur bei primitiven Typen (was hier der Fall ist, da Alter ein Array von Zahlen ist), schlägt jedoch für Objekte fehl.
k0pernikus
Hast du eine Idee, wie es für Objekte mit zwei Schlüsseln funktioniert?
Cegprakash
1
So etwas wieconst uniqueObjects = [ ...new Set( array.map( obj => obj.age) ) ].map( age=> { return array.find(obj => obj.age === age) } )
Harley B
62

Ich würde nur Dups zuordnen und entfernen:

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! Nicht der effizienteste Weg in Bezug auf die Leistung, aber der einfachste und am besten lesbare IMO. Wenn Sie sich wirklich für die Mikrooptimierung interessieren oder große Datenmengen haben, ist eine reguläre forSchleife "effizienter".

elclanrs
quelle
3
@elclanrs - "der leistungsfähigste Weg" - Dieser Ansatz ist langsam .
Travis J
1
@Eevee: Ich verstehe. Die Unterstreichungsversion in Ihrer Antwort ist auch nicht sehr schnell . Ich meine, am Ende entscheiden Sie, was bequemer ist. Ich bezweifle, dass 1-30% mehr oder weniger eine "enorme Verbesserung" bei generischen Tests widerspiegeln und wenn OP / s zu Tausenden sind .
Elclanrs
4
ja sicher. Mit nur drei Elementen ist es am schnellsten, drei Variablen zu erstellen und einige ifs zu verwenden. Mit drei Millionen erhalten Sie sehr unterschiedliche Ergebnisse.
Eevee
1
nicht schnell, aber in meinem Fall hat es den Trick getan, da ich es nicht mit einem großen Datensatz zu tun habe, danke.
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 Beispiel

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]
oleg gabureac
quelle
6
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Alexander
Der erste, der den indexOf gegen den Index verwendet, ist einfach genial.
Leider
Beachten Sie, dass dies nur für primitive Werte funktioniert. Wenn Sie eine Reihe von Daten haben, benötigen Sie einige individuellere Methoden. Lesen Sie hier mehr: codeburst.io/javascript-array-distinct-5edc93501dc4
Molx
36

Für diejenigen, die ein Objekt mit allen Eigenschaften zurückgeben möchten, die nach Schlüssel eindeutig sind

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.

Arun Kumar Saini
quelle
2
Hinweis: Dadurch wird das zuletzt duplizierte Element in der Liste ausgewählt.
Eugene Kulabuhov
1
Fügen Sie dies der Antwort hinzu!
Arun Kumar Saini
1
Genau das, wonach ich gesucht habe. Vielen Dank für das Teilen!
Devner
1
Ich denke, dies sollte die TOP-Antwort sein, um ehrlich zu sein!
Jaroslav Benc
26

Es gibt bereits viele gültige Antworten, aber ich wollte eine hinzufügen, die nur die reduce()Methode verwendet, da sie sauber und einfach ist.

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

Verwenden Sie es so:

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

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

Die forEachVersion der Antwort von @ travis-j (hilfreich für moderne Browser und die Node JS-Welt):

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

34% schneller in Chrome v29.0.1547: http://jsperf.com/filter-versus-dictionary/3

Und eine generische Lösung, die eine Mapper-Funktion übernimmt (etwas langsamer als die direkte Karte, aber das wird erwartet):

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]
Mrchief
quelle
1
Ich mag die generische Lösung am besten, da es unwahrscheinlich ist, dass das Alter der einzige eindeutige Wert ist, der in einem realen Szenario benötigt wird.
Toft
5
Ändern Sie im Generikum "unique.push (key)" in "unique.push (x)", um eine Liste der tatsächlichen Elemente zurückzugeben, die ich für sehr nützlich halte!
Silas Hansen
15

Ich habe standardmäßig damit begonnen, Underscore in alle neuen Projekte einzufügen, damit ich nie über diese kleinen Probleme beim Datenmunging nachdenken muss.

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

Produziert [17, 35].

Eevee
quelle
13

Hier ist ein anderer Weg, um dies zu lösen:

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

Ich habe keine Ahnung, wie schnell diese Lösung im Vergleich zu den anderen ist, aber ich mag das sauberere Aussehen. ;-);


EDIT: Okay, das oben genannte scheint die langsamste Lösung von allen hier zu sein.

Ich habe hier einen Leistungstestfall erstellt: http://jsperf.com/distinct-values-from-array

Anstatt nach dem Alter (Integer) zu testen, habe ich die Namen (Strings) verglichen.

Methode 1 (TS-Lösung) ist sehr schnell. Interessanterweise übertrifft Methode 7 alle anderen Lösungen. Hier habe ich gerade .indexOf () entfernt und eine "manuelle" Implementierung verwendet, um das Aufrufen von Schleifenfunktionen zu vermeiden:

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

Der Leistungsunterschied bei Safari & Firefox ist erstaunlich und Chrome scheint bei der Optimierung die beste Arbeit zu leisten.

Ich bin mir nicht ganz sicher, warum die obigen Schnipsel im Vergleich zu den anderen so schnell sind. Vielleicht hat jemand, der klüger als ich ist, eine Antwort. ;-);

BaM
quelle
9

mit lodash

var array = [
    { "name": "Joe", "age": 17 },
    { "name": "Bob", "age": 17 },
    { "name": "Carl", "age": 35 }
];
_.chain(array).pluck('age').unique().value();
> [17, 35]
Ivan Nosov
quelle
2
Können Sie erklären, wie dies mit einfachem Javascript gemacht wird, wie in der Frage impliziert?
Ruskin
es ist eine Unterstrichfunktion _.chain
vini
2
aber zupfen () ist nicht in lodash.
Yash Vekaria
1
_.chain (array) .map ('age'). unique (). value (); arbeitete für mich.
Yash Vekaria
Version 4.0 hatte einige bahnbrechende Änderungen zu verweisen - stackoverflow.com/a/31740263/4050261
Adarsh ​​Madrecha
7

Verwenden von Lodash

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

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

Rückgabe [17,35]

Yash Vekaria
quelle
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;
}
Dmitriy Kupriyanov
quelle
5

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

Radosław Kopczyński
quelle
5
Bitte fügen Sie eine Erklärung hinzu, wie dies die Frage beantwortet.
Roboter-Katze
2
_.pluck wurde zugunsten von _.map entfernt
Ajax3.14
5

Hier ist eine vielseitige Lösung, die Reduzieren verwendet, Mapping ermöglicht und die Einfügereihenfolge beibehält.

Artikel : Ein Array

Mapper : Eine unäre Funktion, die das Element den Kriterien zuordnet oder leer ist, um das Element selbst zuzuordnen.

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

Verwendungszweck

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

Sie können dies Ihrem Array-Prototyp hinzufügen und den Parameter items weglassen, wenn dies Ihr Stil ist ...

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

Sie können auch ein Set anstelle eines Arrays verwenden, um den Abgleich zu beschleunigen.

function distinct(items, mapper) {
    if (!mapper) mapper = (item)=>item;
    return items.map(mapper).reduce((acc, item) => {
        acc.add(item);
        return acc;
    }, new Set());
}
Steven Spungin
quelle
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' } 
]
*/

Ruben Morales Felix
quelle
2
das sieht aus wie O (n ^ 2)
cegprakash
4

Ich habe das gerade gefunden und fand es nützlich

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

Verwenden Sie wieder den Unterstrich . Wenn Sie also ein solches Objekt haben

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

Sie erhalten nur die eindeutigen Objekte.

Was hier passiert, ist, dass indexByeine Karte wie diese zurückgegeben wird

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

und nur weil es eine Karte ist, sind alle Schlüssel eindeutig.

Dann ordne ich diese Liste einfach wieder dem Array zu.

Falls Sie nur die unterschiedlichen Werte benötigen

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

Denken Sie daran, dass das keyals Zeichenfolge zurückgegeben wird. Wenn Sie stattdessen Ganzzahlen benötigen, sollten Sie dies tun

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

Ich denke, Sie suchen nach GroupBy-Funktion (mit Lodash)

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

erzeugt Ergebnis:

17,35

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

Amil Sajeev
quelle
3

Wenn Sie wie ich eine "funktionalere" Version bevorzugen, ohne die Geschwindigkeit zu beeinträchtigen, wird in diesem Beispiel eine schnelle Wörterbuchsuche verwendet, die in den Verschluss reduziert ist.

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

Nach diesem Test ist meine Lösung doppelt so schnell wie die vorgeschlagene Antwort

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

Ich weiß, dass mein Code wenig lang und wenig zeitlich komplex ist, aber es ist verständlich, also habe ich es auf diese Weise versucht.

Ich versuche hier eine prototypbasierte Funktion zu entwickeln und auch den Code zu ändern.

Hier ist Distinct meine eigene Prototypfunktion.

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

Prabhat
quelle
2

Wenn Sie Array.prototype.includes haben oder bereit sind, es zu füllen , funktioniert dies:

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

Mein unten stehender Code zeigt das eindeutige Altersarray sowie das neue Array ohne doppeltes Alter

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);```
Shridhar Sagari
quelle
1

Ich habe mein eigenes in TypeScript geschrieben, für einen generischen Fall, wie den in Kotlins 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)));
}

Wo Uist Hashhable natürlich. Für Objekte benötigen Sie möglicherweise https://www.npmjs.com/package/es6-json-stable-stringify

Polv
quelle
1

Für den Fall, dass Sie ein Unikat des gesamten Objekts benötigen

const _ = require('lodash');

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

_.uniqWith(objects, _.isEqual);

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

Cegprakash
quelle
Downvoter: Möchtest du erklären, warum die Downvote?
Cegprakash
1

Die Beantwortung dieser alten Frage ist ziemlich sinnlos, aber es gibt eine einfache Antwort, die auf die Natur von Javascript hinweist. Objekte in Javascript sind von Natur aus Hash-Tabellen. Wir können dies verwenden, um einen Hash eindeutiger Schlüssel zu erhalten:

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

Dann können wir den Hash auf ein Array eindeutiger Werte reduzieren:

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

Das ist alles was du brauchst. Das Array a2 enthält nur das eindeutige Alter.

Preston L. Bannister
quelle
1

Einfacher Einzeiler mit großartiger Leistung. 6% schneller als die ES6-Lösungen in meinen Tests .

var ages = array.map(function(o){return o.age}).filter(function(v,i,a) {
    return a.indexOf(v)===i
});
Craig
quelle
@ Jeb50 Möchten Sie eine mehrzeilige Zeile hinzufügen, die einfach zu lesen ist? Wenn ich mir die anderen hier ansehe, habe ich wirklich nicht das Gefühl, dass sie leicht zu lesen oder zu verstehen sind. Ich denke, es ist am besten, dies in eine Funktion zu setzen, die beschreibt, was es tut.
Craig
2
Mit Pfeilfunktionen : array.map( o => o.age).filter( (v,i,a) => a.indexOf(v)===i). Ich benutze das Funktionsschlüsselwort jetzt so selten, dass ich Dinge zweimal lesen muss, wenn ich es sehe 😊
Drenai