Underscore.jsを使用してオブジェクトから空のプロパティ/偽の値を削除します


83

いくつかのプロパティを持つオブジェクトがあります。偽の値を持つプロパティを削除したいと思います。

これはcompactonarrayで実現できますが、オブジェクトについてはどうでしょうか。


これをリポジトリ間でコピーして貼り付けないようにするには、Bitを使用してこのコンポーネントインポートします(3つのテストに合格し、MITライセンスがあります)。このNPMパッケージを試すこともできます(これは小さなコンポーネントにとってはやり過ぎかもしれません)。
ヨニ2017

回答:


47

あなたはあなた自身のアンダースコアプラグイン(mixin)を作ることができます:

_.mixin({
  compactObject: function(o) {
    _.each(o, function(v, k) {
      if(!v) {
        delete o[k];
      }
    });
    return o;
  }
});

そして、それをネイティブアンダースコアメソッドとして使用します。

var o = _.compactObject({
  foo: 'bar',
  a: 0,
  b: false,
  c: '',
  d: null,
  e: undefined
});

更新

@AndreiNeculauが 指摘元ながら、このミックスインは、元のオブジェクトに影響を与えるcompactアンダー方法は配列のコピーを返します
この問題を解決し、私たちのようにするにはcompactObjectより多くのそれのように振る舞うのいとこ、ここではマイナーなアップデートです:

_.mixin({
  compactObject : function(o) {
     var clone = _.clone(o);
     _.each(clone, function(v, k) {
       if(!v) {
         delete clone[k];
       }
     });
     return clone;
  }
});

1
質問にはアンダースコアの参照があるため、これはのように動作しないことに言及しておくとよいでしょう_.compact。真の値のみで浅いクローンを作成するのではなく、プロパティを削除します。以下のstackoverflow.com/a/19750822/465684を参照してください
Andrei Neculau 2014年

@AndreiNeculauその通りです!私は以前にそれを逃したようです。私の更新された答えを参照してください。
gion_13 2014年

3
なぜ最初にオブジェクトのすべてのプロパティをコピーし、次にそれらをループして偽のプロパティを削除するのですか?それはパフォーマンスが悪いです。さらに、deleteプロトタイプチェーンから同じ名前のプロパティがすぐに公開され、「非表示のクラス」(V8)が原因でパフォーマンスが低下するため、使用は一般的に推奨されていません。オブジェクト構造を変更すると、エンジンが余分な作業を行うことになります。最良かつ最短の解決策はです_.pick(o, _.identity)
Radko Dinev 2014年

170

アンダースコアバージョン1.7.0以降、次のものを使用できます_.pick

_.pick(sourceObj, _.identity)

説明

2番目のパラメーターは、_.pick値を選択するための述語関数にすることができます。述部がを返す値が選択され、述部がを返すは無視されます。

pick _.pick(object、* keys)

ホワイトリストに登録されたキー(または有効なキーの配列)の値のみを持つようにフィルタリングされた、オブジェクトのコピーを返します。または、選択するキーを示す述語を受け入れます。

_.identityは、最初の引数を返すヘルパー関数です。つまり、真の値を選択し、偽の値を拒否する述語関数としても機能します。アンダースコアライブラリには、他にも多数の述語が付属してい_.pick(sourceObj, _.isBoolean)ます。たとえば、ブールプロパティのみを保持します。

この手法を頻繁に使用する場合は、もう少し表現力を高めたいと思うかもしれません。

var pickNonfalsy = _.partial(_.pick, _, _.identity); // Place this in a library module or something
pickNonfalsy(sourceObj);

アンダースコアバージョン1.6.0も提供さ_.pickれましたが、ホワイトリストの代わりに述語関数を受け入れませんでした。


2
_.identity機能について言及してくれてありがとう、とても便利です。
ivkremer 2015年

9
これは非常に便利です!_.omit(sourceObj, _.isUndefined)未定義の値(false、null、0を許可)のみを削除するために使用することもできます。
ベンパターソン

1
pick(obj, Boolean)偽の値arr.filter(Boolean)から配列をクリーンアップするときに同じアプローチを使用できる偽の値を排除することも可能です...–
David Chase

3
ES6では、これは次のようになります_.pick(sourceObj, prop => prop)
Deniz Ozger 2015

16
lodash 4.4.0_.pickでは、プロパティ名で動作します。使用後の説明にあるように、この機能については_.pickBy
zooblin 2016

45

クイック 'nクリア: _.omitBy( source, i => !i );

これは、エミルの答えとは逆の方法で述べられています。このようにして、imhoはより明確に読みます。それはもっと自明です。

ES6の贅沢がない場合は、少しきれいではありません。 _.omitBy( source, function(i){return !i;});

代わりの: _.omitBy( source, _.isEmpty)

真実性の_.isEmpty代わりに_.identityを使用すると、コレクションから空の配列とオブジェクトが便利に削除され、おそらく不便なことに数値と日付が削除されます。したがって、結果はOPの質問に対する正確な答えではありませんが、空のコレクションを削除する場合に役立つ可能性があります。


8
Lodash 4.0では、この機能は現在omitBy。の下にあります。lodash.com/docs#omitBy
JackMorrissey 2016

3
これは次と同じだと思います: _.pick(source, i => i); 否定を回避します
Jeff Lowery

2
@JeffLoweryデフォルトの述語は恒等関数であるため、Lodashではこれはさらに優れています。_.pickBy(source)必要なのはそれだけです。
渋見2018

注:番号は空と見なされます。_.isEmpty(5) === true。したがって、数値である値は削除されます。
サー・ネイサン・スタッセン

21

lodashの変換で

_.transform(obj, function(res, v, k) {
  if (v) res[k] = v;
});

23
聖霊降臨祭のlodashの_.pick(obj、_。identity); 短い^ _ ^
悪意のある2014

この答えまたはその下の@eviliveのコメントが答えです。
Radko Dinev 2014年

2
上記のコメントに基づくより短いバリエーションは、次のようになりますvar compactObject = _.partialRight(_.pick, _.identity);
zaboco 2014年


yse、_.pickBy(object)必要なのはそれだけです
wdetac 2018年

19
Object.keys(o).forEach(function(k) {
    if (!o[k]) {
        delete o[k];
    }
});

1
そして、.keysとにアンダースコアを使用できます.forEach
Felix Kling 2012

では、これはアンダースコアでどのように見えるでしょうか?それをつなぎ

+1これはすごい人です。forEachJSの方法のリンクを教えてください
diEcho 2013年


9

浅いクローンを作成できます。

_(obj).reduce(function(a,v,k){ 
     if(v){ a[k]=v; } 
     return a; 
},{});

5

オブジェクトの場合は削除します。

for(var k in obj){

  if(obj.hasOwnProperty(k) && !obj[k]){
    delete obj[k];
  }
}

彼はアンダースコアソリューションを望んでいるので、アンダースコアの方法の1つを使用して配列を反復処理できます
gion_13 2012

5

突然、再帰的に偽物を削除する関数を作成する必要がありました。これがお役に立てば幸いです。Lodashを使用しています。

var removeFalsies = function (obj) {
    return _.transform(obj, function (o, v, k) {
        if (v && typeof v === 'object') {
            o[k] = _.removeFalsies(v);
        } else if (v) {
            o[k] = v;
        }
    });
};

_.mixin({ 'removeFalsies': removeFalsies });

次に、それを使用できます。

var o = _.removeFalsies({
  foo: 'bar',
  a: 0,
  b: false,
  c: '',
  d: null,
  e: undefined,
  obj: {
    foo: 'bar',
    a: 0,
    b: false,
    c: '',
    d: null,
    e: undefined
  }
});

// {
//   foo: 'bar',
//   obj: {
//     foo: 'bar'
//   }
// }

1

gion_13の答えに追加するには:

_.mixin({
  compactObject : function(o) {
     var newObject = {};
     _.each(o, function(v, k) {
       if(v !== null && v !== undefined) {
         newObject[k] = v
       }
     });
     return newObject;
  }
});

これは、すべてを複製してキーと値のペアを削除する代わりに、新しいオブジェクトを作成し、キーと値を追加します。マイナーな違い。

しかし、もっと重要なことは、falseの代わりにnullとundefinedを明示的にチェックすることです。これにより、値としてfalseを持つキーと値のペアが削除されます。



-1

けれどもは、_.compact配列で使用するために文書化されています。オブジェクトに対しても機能するようです。Chrome、Opera、Firefoxコンソールで以下を実行しました。

var obj = {first: 1, second: null, third: 3, fourth: function(){return 5}}
undefined
_.compact(obj)

[1, 3, function()]

更新:サンプルが示すよう_.compactに、オブジェクトを呼び出すとキーが削除され、圧縮された配列が返されます。


1
ただし、それでも配列を返します。キーが失われます。
Turadg 2016

1
あなたが正しい。その後、回答を削除しますか?それともstackoverflowは他のものを好みますか?
tzvi 2016年

2
コミュニティの好みはわかりませんが、そのままにしておいても問題がなければ、他の誰かが同様の回答を追加するのを防ぐ価値があるかもしれません。
Turadg 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.