オブジェクトがあるとしましょう。
{
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
}
上記のオブジェクトをフィルタリングして別のオブジェクトを作成したいので、次のようにします。
{
item1: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
}
Es6を使用してこれを達成するためのクリーンな方法を探しているので、スプレッド演算子を使用できます。ありがとうございます。
許可された値のリストがある場合、次を使用してそれらをオブジェクトに簡単に保持できます。
const raw = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const allowed = ['item1', 'item3'];
const filtered = Object.keys(raw)
.filter(key => allowed.includes(key))
.reduce((obj, key) => {
obj[key] = raw[key];
return obj;
}, {});
console.log(filtered);
これは以下を使用します:
Object.keys
raw
(元のデータ)内のすべてのプロパティを一覧表示するには、Array.prototype.filter
は、を使用して許可リストに存在するキーを選択しますArray.prototype.includes
存在することを確認するArray.prototype.reduce
許可されたプロパティのみで新しいオブジェクトを構築します。これにより、許可されたプロパティを使用して浅いコピーが作成されます(ただし、プロパティ自体はコピーされません)。
オブジェクトスプレッド演算子 を使用して、オブジェクトを変更せずに一連のオブジェクトを作成することもできます( これについて言及したrjerue )。
const raw = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const allowed = ['item1', 'item3'];
const filtered = Object.keys(raw)
.filter(key => allowed.includes(key))
.reduce((obj, key) => {
return {
...obj,
[key]: raw[key]
};
}, {});
console.log(filtered);
雑学の目的で、元のデータから不要なフィールドを削除したい場合(ifい突然変異を伴うため、(は推奨しません推奨しません)) 、次のようにincludes
チェックを反転できます。
const raw = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const allowed = ['item1', 'item3'];
Object.keys(raw)
.filter(key => !allowed.includes(key))
.forEach(key => delete raw[key]);
console.log(raw);
突然変異ベースのソリューションを示すためにこの例を含めていますが、使用することはお勧めしません。
ES6の構文を使用しても問題ない場合は、 here および here に記載されているように、これを実行する最も簡単な方法は次のとおりです。
const data = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const { item2, ...newData } = data;
今、newData
は次のものを含みます。
{
item1: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
または、キーを文字列として格納している場合は、次のようにします。
const key = 'item2';
const { [key]: _, ...newData } = data;
後者の場合、[key]
はitem2
に変換されますが、const
割り当てを使用しているので、割り当ての名前を指定する必要があります。 _
は使い捨ての値を表します。
より一般的には:
const { item2, ...newData } = data; // Assign item2 to item2
const { item2: someVarName, ...newData } = data; // Assign item2 to someVarName
const { item2: _, ...newData } = data; // Assign item2 to _
const { ['item2']: _, ...newData } = data; // Convert string to key first, ...
これはあなたの操作をワンライナーに減らすだけでなく、他のキーが何であるか(あなたが保存したいもの)を知っている必要もありません。
最もきれいな方法は Lodash#pick です。
const _ = require('lodash');
const allowed = ['item1', 'item3'];
const obj = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
}
const filteredObj = _.pick(obj, allowed)
これまでに述べられたことは何もありませんが、いくつかの答えをES6の一般的な答えに組み合わせます。
const raw = {
item1: { key: 'sdfd', value: 'sdfd' },
item2: { key: 'sdfd', value: 'sdfd' },
item3: { key: 'sdfd', value: 'sdfd' }
};
const filteredKeys = ['item1', 'item3'];
const filtered = filteredKeys
.reduce((obj, key) => ({ ...obj, [key]: raw[key] }), {});
console.log(filtered);
1行のコードでの別の解決策 。
私は " Destructuring "機能で遊んでいました:
const raw = {
item1: { key: 'sdfd', value: 'sdfd' },
item2: { key: 'sdfd', value: 'sdfd' },
item3: { key: 'sdfd', value: 'sdfd' }
};
var myNewRaw = (({ item1, item3}) => ({ item1, item3 }))(raw);
console.log(myNewRaw);
一般的なofilter
(一般的なoreduce
を使って実装されています)を追加することができますので、配列と同じように簡単にオブジェクトをフィルタリングすることができます -
const oreduce = (f, acc, o) =>
Object
.entries (o)
.reduce
( (acc, [ k, v ]) => f (acc, v, k, o)
, acc
)
const ofilter = (f, o) =>
oreduce
( (acc, v, k, o)=>
f (v, k, o)
? Object.assign (acc, {[k]: v})
: acc
, {}
, o
)
我々はそれがここで働いているのを見ることができます -
const data =
{ item1: { key: 'a', value: 1 }
, item2: { key: 'b', value: 2 }
, item3: { key: 'c', value: 3 }
}
console.log
( ofilter
( (v, k) => k !== 'item2'
, data
)
// [ { item1: { key: 'a', value: 1 } }
// , { item3: { key: 'c', value: 3 } }
// ]
, ofilter
( x => x.value === 3
, data
)
// [ { item3: { key: 'c', value: 3 } } ]
)
下記のブラウザで結果を確認してください -
const oreduce = (f, acc, o) =>
Object
.entries (o)
.reduce
( (acc, [ k, v ]) => f (acc, v, k, o)
, acc
)
const ofilter = (f, o) =>
oreduce
( (acc, v, k, o)=>
f (v, k, o)
? Object.assign (acc, { [k]: v })
: acc
, {}
, o
)
const data =
{ item1: { key: 'a', value: 1 }
, item2: { key: 'b', value: 2 }
, item3: { key: 'c', value: 3 }
}
console.log
( ofilter
( (v, k) => k !== 'item2'
, data
)
// [ { item1: { key: 'a', value: 1 } }
// , { item3: { key: 'c', value: 3 } }
// ]
, ofilter
( x => x.value === 3
, data
)
// [ { item3: { key: 'c', value: 3 } } ]
)
これら2つの機能は、さまざまな方法で実装できます。私はoreduce
の中でArray.prototype.reduce
にアタッチすることを選びました、しかし、あなたはまったく同じようにゼロからそれをすべて書くことができます
これが私の最近のやり方です。
const dummyObj = Object.assign({}, obj);
delete dummyObj[key];
const target = Object.assign({}, {...dummyObj});
ssube's answeranswer にピギーバックします。
これが再利用可能なバージョンです。
Object.filterByKey = function (obj, predicate) {
return Object.keys(obj)
.filter(key => predicate(key))
.reduce((out, key) => {
out[key] = obj[key];
return out;
}, {});
}
それを呼び出すには
const raw = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const allowed = ['item1', 'item3'];
var filtered = Object.filterByKey(raw, key =>
return allowed.includes(key));
});
console.log(filtered);
ES6のarrow関数のすばらしいところは、allowed
をパラメータとして渡す必要がないことです。
あなたはこのようなことをすることができます:
const base = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const filtered = (
source => {
with(source){
return {item1, item3}
}
}
)(base);
// one line
const filtered = (source => { with(source){ return {item1, item3} } })(base);
これは機能しますが、あまり明確ではありません。さらにwith
ステートメントはお勧めできません( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with )。
Object.entries()
の代わりにObject.keys()
を使用すると、filter
を使用しないでより簡単なソリューションを実現できます。
const raw = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const allowed = ['item1', 'item3'];
const filtered = Object.entries(raw).reduce((acc,Elm)=>{
const [k,v] = Elm
if (allowed.includes(k)) {
acc[k] = v
}
return acc
},{})
さて、このワンライナーはどうですか
const raw = {
item1: { key: 'sdfd', value: 'sdfd' },
item2: { key: 'sdfd', value: 'sdfd' },
item3: { key: 'sdfd', value: 'sdfd' }
};
const filteredKeys = ['item1', 'item3'];
const filtered = Object.assign({}, ...filteredKeys.map(key=> ({[key]:raw[key]})));
ここでの答えは確かに適していますが、オブジェクト内のすべてのプロパティに対してホワイトリストをループ処理する必要があるため、少し時間がかかります。以下の解決策は、ホワイトリストを1回だけループ処理するため、大規模なデータセットに対してははるかに高速です。
const data = {
allowed1: 'blah',
allowed2: 'blah blah',
notAllowed: 'woah',
superSensitiveInfo: 'whooooah',
allowed3: 'bleh'
};
const whitelist = ['allowed1', 'allowed2', 'allowed3'];
function sanitize(data, whitelist) {
return whitelist.reduce(
(result, key) =>
data[key] !== undefined
? Object.assign(result, { [key]: data[key] })
: result,
{}
);
}
sanitize(data, whitelist)
Object.fromEntriesメソッドを使用することで、短く簡単にすることができます(ブラウザサポートを確認してください)。
const raw = { item1: { prop:'1' }, item2: { prop:'2' }, item3: { prop:'3' } };
const allowed = ['item1', 'item3'];
const filtered = Object.fromEntries(Object.entries(raw).filter(([key, val])=>allowed.includes(key)));
続きを読む: Object.fromEntries
[OK]を /これはどうですか:
const myData = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
function filteredObject(obj, filter) {
if(!Array.isArray(filter)) {
filter = [filter.toString()];
}
const newObj = {};
for(i in obj) {
if(!filter.includes(i)) {
newObj[i] = obj[i];
}
}
return newObj;
}
そしてこれを次のように呼ぶ:
filteredObject(myData, ['item2']); //{item1: { key: 'sdfd', value:'sdfd' }, item3: { key: 'sdfd', value:'sdfd' }}
ループ中に、特定のプロパティ/キーに遭遇したときは何もせずに残りを続けます。
const loop = product =>
Object.keys(product).map(key => {
if (key === "_id" || key === "__v") {
return;
}
return (
<ul className="list-group">
<li>
{product[key]}
<span>
{key}
</span>
</li>
</ul>
);
});
この関数はキーのリストに基づいてオブジェクトをフィルタリングします。これは、reduceを呼び出す前にArray.filterを使用する必要がないため、前の回答よりも効率的です。 O(n +フィルタ処理)とは対照的に、そのO(n)
function filterObjectByKeys (object, keys) {
return Object.keys(object).reduce((accum, key) => {
if (keys.includes(key)) {
return { ...accum, [key]: object[key] }
} else {
return accum
}
}, {})
}
オブジェクトの特定のキーを削除できます
items={
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
}
// Example 1
var key = "item2";
delete items[key];
// Example 2
delete items["item2"];
// Example 3
delete items.item2;
これを実現するには多くの方法があります。 受け入れられた答え は最も効果的ではないKeys-Filter-Reduceアプローチを使用します。
代わりに、for...in
ループを使用してオブジェクトのキーをループ処理するか、許可されているキーをループ処理し、 then を使用すると、パフォーマンスが最大50%向上します。ある。
const obj = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const keys = ['item1', 'item3'];
function keysReduce (obj, keys) {
return keys.reduce((acc, key) => {
if(obj[key] !== undefined) {
acc[key] = obj[key];
}
return acc;
}, {});
};
function forInCompose (obj, keys) {
const returnObj = {};
for (const key in obj) {
if(keys.includes(key)) {
returnObj[key] = obj[key]
}
};
return returnObj;
};
keysReduce(obj, keys); // Faster if the list of allowed keys are short
forInCompose(obj, keys); // Faster if the number of object properties are low
a。単純なユースケースのベンチマークについては jsPerf を参照してください。結果はブラウザによって異なります。