2017-07-16 12 views
1

配列をユニークな値でフィルタリングする方法はたくさんありますが、特定のフィールドにユニークな値を持つオブジェクトの配列をフィルタリングする方法はありますか?例えばユニークなフィールド値のフィルタ配列

各オブジェクトは、次の形式である場合、私は[obj1, obj2, obj3, ...]を持っている:

{ 
firstName: "...", 
lastName: "..." 
} 

どのように私はすべてのオブジェクトは、独自のファーストネームを持って、最終的な配列で終わるために、配列をフィルタリングすることができますか? 1つのライナーは読みやすくすることはできませんが、より良いでしょう。

あなたが最初の名前がす​​でに存在していない場合は、条件付きで、すなわち、新しい配列への配列、プッシュ対象となる reduce方法、および設定した初期値を使用することができます
+0

を、1-ライナーです: 'arr.filter((E、I)=> arr.findIndex (e2 => e.firstName === e2.firstName)=== i) ' – frozen

答えて

3

フィルターのみで配列の前に見つからない項目。 condは、2つの項目を「等しい」とみなすべきかどうかを返すものとして定義します。

function uniqueBy(a, cond) { 
 
    return a.filter((e, i) => a.findIndex(e2 => cond(e, e2)) === i); 
 
} 
 

 
const test = [ 
 
    { firstname: "John", lastname: "Doe" }, 
 
    { firstname: "Jane", lastname: "Doe" }, 
 
    { firstname: "John", lastname: "Smith" } 
 
]; 
 

 
console.log(uniqueBy(test, (o1, o2) => o1.firstname === o2.firstname));

1

どう

var arr = [ { firstname: "John", 
 
       lastname: "Doe" }, 
 
      { firstname: "Jane", 
 
       lastname: "Doe" }, 
 
      { firstname: "John", 
 
       lastname: "Doe" }]; 
 
       
 

 
console.log(
 
    arr.reduce(
 
    function(unique_arr, obj) { 
 
     if(!unique_arr.some(x => x.firstname === obj.firstname)) { 
 
     unique_arr.push(obj) 
 
     } 
 
     return unique_arr; 
 
    }, []) 
 
);

+0

なぜ矢印関数を内部的に使用するのか不思議ですが、reduceの伝統的な関数リテラルです。この嗜好か意図していないのですか、まともなスタイルルールがありますか? – vol7ron

+0

@ vol7ronそれは意図的なものではなく、また、reduceの関数が内部の単純な矢印関数よりも少し複雑なので、私は推測します。 – Psidom

0

を約2ライナー。

var ar = [{firstName: 'Jo'}, {firstName: 'Bill'}, {firstName: 'Bill'}]; 
 

 
var firstNames = []; 
 
var uniqueFirstName = ar.filter(obj => 
 
    firstNames.indexOf(obj.firstName) > -1 
 
     ? false : firstNames.push(obj.firstName)) 
 
console.log(JSON.stringify(uniqueFirstName));

+0

これをスニペットでラップして、実際に動作を確認できますか?これは、一意のファーストネームのリスト、またはOPが望むように一意のファーストネームを持つオブジェクトのリストを返しますか? –

+0

@torazaburoオブジェクトのリストを返す必要があります –

2

あなたはMapに、配列を減らし、再び配列にマップ値を広げることができます。

最初のオブジェクトを保持したい場合は、マップに既にfirstNameがキーであるかどうかをチェックし、マップがまだ存在しない場合にのみ設定する必要があります。

const arr = [{"firstname":"Robert","lastname":"Smith"},{"firstname":"Francis","lastname":"Collins"},{"firstname":"Robert","lastname":"Ludlum"},{"firstname":"Francis","lastname":"bacon"}]; 
 
       
 
const result = [...arr.reduce((map, obj) => map.has(obj.firstname) ? map : map.set(obj.firstname, obj), new Map()).values()]; 
 

 
console.log(result);

あなたが最後のオブジェクトを保持したい場合は、チェックをスキップして、ちょうどそれらを設定することができます。

const arr = [{"firstname":"Robert","lastname":"Smith"},{"firstname":"Francis","lastname":"Collins"},{"firstname":"Robert","lastname":"Ludlum"},{"firstname":"Francis","lastname":"bacon"}]; 
 

 
const result = [...arr.reduce((map, obj) => map.set(obj.firstname, obj), new Map()).values()]; 
 

 
console.log(result);

0

に必要とせずに、あなたの結果の配列が値を持っていますが、独自性のために、私はオブジェクトを使用し、常に値を設定することがより簡単に、より扱い発見した場合の答えは、チェックの意図に見えますそれを確認してください。これは、オブジェクトが唯一のユニークなキーを持っていることを前提に依存しています:torazaburoの答えから

var arr = [{ 
 
    firstName: "Amy", 
 
    lastName: "Adams" 
 
    }, 
 
    { 
 
    firstName: "Bryan", 
 
    lastName: "Heart" 
 
    }, 
 
    { 
 
    firstName: "Amy", 
 
    lastName: "Adams" 
 
    } 
 
]; 
 

 

 
var unique = {}; 
 

 
for (var i = 0, n = arr.length; i < n; i++) { 
 
    // Key is your unique condition 
 
    var key = [arr[i].firstName, arr[i].lastName].join(' '); 
 
    unique[key] = arr[i]; 
 
} 
 

 
console.log('Keys:', Object.keys(unique));  // only shown for austerity 
 
console.log('Values:', Object.values(unique));

関連する問題