【问题标题】:Filter object properties by key in ES6在 ES6 中按键过滤对象属性
【发布时间】:2016-12-09 14:16:43
【问题描述】:

假设我有一个对象:

{
  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 完成此任务的简洁方法,因此我可以使用扩展运算符。

【问题讨论】:

  • ES6 没有对象扩展操作符,你也不需要它们
  • @DanDascalescu 但是this answer 提供了一种 ES6 方式来完成 OP 的要求,不是吗?
  • 如果我想按键/值过滤怎么办?

标签: javascript ecmascript-6 filter


【解决方案1】:

如果您有一个允许值的列表,您可以使用以下方法轻松地将它们保留在对象中:

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

这个用途:

  1. Object.keys 列出raw 中的所有属性(原始数据),然后
  2. Array.prototype.filter 选择允许列表中存在的键,使用
    1. Array.prototype.includes 确保他们在场
  3. Array.prototype.reduce 构建仅具有允许属性的新对象。

这将使用允许的属性进行浅拷贝(但不会复制属性本身)。

您还可以使用the object spread operator 创建一系列对象而不改变它们(感谢rjerue for mentioning this):

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

出于琐事的目的,如果您想从原始数据中删除不需要的字段(我不会建议这样做,因为它涉及一些丑陋的突变),您可以反转 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);

我包含这个示例是为了展示基于突变的解决方案,但我不建议使用它。

【讨论】:

  • 谢谢,效果很好。我还找到了一种使用“解构语法”的方法。 IE : 常量 {item1,item3} = 原始常量 newObject = {item1,item3}
  • 解构会起作用(很好),但纯粹是编译时的。您不能将其设为动态属性列表或提供任何复杂规则(例如,循环可以附加验证回调)。
  • 我不能给这个足够的投票!使用过滤器和减少而不是从 for 循环构造另一个对象做得很好。真棒,你明确地分离了不可变和可变版本。 +1
  • 快速警告:Array.prototype.includes 不是 ES6 的一部分。它是在 ECMAScript 2016 (ES7) 中引入的。
  • 如果你想以不可变的方式做 reduce,你也可以用 return { ...obj, [key]: raw[key] } 替换函数内容
【解决方案2】:

如果您可以使用 ES6 语法,我发现最简洁的方法是:如 herehere 所述:

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

这不仅将您的操作简化为单行,而且还不需要您知道其他键是什么(您要保留的键)。

一个简单的实用函数如下所示:

function removePropFromObject(obj, prop) {
  const { [prop]: _, ...rest } = obj
  return { ...rest }
}

【讨论】:

  • "_ 表示丢弃值"这是从哪里来的?第一次见
  • 我相信这是 JS 社区采用的惯例。 _ 只是一个可以在 JS 中使用的有效变量名,但由于它几乎是无名的,如果你想传达意图,它真的不应该以这种方式使用。因此,它被用作表示您不关心的变量的一种方式。以下是关于它的进一步讨论:stackoverflow.com/questions/11406823/…
  • 这比公认的答案更整洁,避免了使用 Object.keys() 创建新数组的开销,以及使用 filterreduce 迭代数组的开销。跨度>
  • @yhabib _ 没关系,只是一个变量名,你可以重命名为任何你想要的名字
  • @Gerrat 我认为通用解决方案不会是微不足道的单线。为此,我会使用 lodash 的 omit 函数:lodash.com/docs/4.17.10#omit 或此处给出的其他解决方案之一。
【解决方案3】:

没有什么以前没有说过的,而是将一些答案结合到一个通用的 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);

【讨论】:

  • 这是一个比其他解决方案更简单、更高效的解决方案;)
  • 好简洁的解决方案。请注意,如果filteredKeys 中有一个不在raw 中的键,则该键将显示在filtered 中,其值为undefined。在其他答案中,该密钥根本不会出现在 filtered 中。
【解决方案4】:

你能找到的最干净的方法是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)

【讨论】:

  • 重要的是要指出,为此必须在运行时下载额外的项目依赖项。
  • _.omit(obj, ["item2"]) - lodash.omit 是 lodash.pick 的对立面
  • 如果你使用 Ramda,还有 ramda.pick! ramdajs.com/docs/#pick
【解决方案5】:

您现在可以使用 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

【讨论】:

  • 这是我认为最好的方式。比 reduce 更直观。
  • 记录在案。将Object.fromEntriesTypescript 一起使用时,请确保"lib": ["ES2019"]tsconfig.json 中设置
  • 我喜欢 entries/fromEntries 技巧,但如果它是一个大对象,可能会影响性能 - jsbench.me/3ukxxhfgjr/1
【解决方案6】:

一行 Modern JS 中的另一种解决方案,没有外部库

我在玩“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);

【讨论】:

  • var myNewRaw = (({ item1, item3}) => ({ item1, item3 }))(raw); 语法问题
  • 这里浓缩了几件事: 首先,是函数的声明。它是一个箭头函数(它接受一个对象并返回一个对象)。它与 function(obj){return obj;} 相同。第二件事是 ES6 允许解构未来。在我的函数声明中,我解构了我的对象{ item1, item3}。最后一件事是我自己调用我的函数。例如,您可以使用自调用功能来管理您的范围。但这里只是为了压缩代码。我希望很清楚。如果我错过了什么,请随时添加。
  • 这是首选的现代方法恕我直言
  • accepted answer 将仅包含过滤器列表中且存在于原始数据中的键。我相信您的答案将插入缺少的键,并以undefined 作为值,例如,如果我的原始数据不包含item3,我认为您的代码会添加它。可能存在不受欢迎的用例。 (对于我的用例来说很好!我正在使用它!)
  • @NikaKasradze 没有这些括号,函数将返回未定义。 Awol 确实在第一次帮助我解决了这一点。在阅读博客并阅读规范后,我对它的理解更好。如果您不介意,它会在另一条评论中尝试简要说明。
【解决方案7】:

好的,这个单线怎么样

    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
  • 如果您只知道要删除的键...而不是要保留的键怎么办?
【解决方案8】:

在允许的键上使用Array.reduce 方法的另一种解决方案:

const raw = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

const allowed = ['item1', 'item3'];

const filtered = allowed.reduce((obj, key) => { 
  obj[key] = raw[key]; 
  return obj 
}, {})

console.log(filtered);

特别是对于较大的源对象(本例中为原始对象),这将是有意义的。迭代不会使用源的所有条目执行,而只会使用您要过滤的键,因此更短/更快...

Demonstration in this Fiddle...


但我不得不说我也喜欢this answer here 中使用Object.fromEntries Array.filterArray.includes 的解决方案:

const object = Object.fromEntries(
  Object.entries(raw).filter(([key, value]) => allowed.includes(key))
);

Demonstration in this Fiddle...

【讨论】:

  • 威尔特,您的第二种方法与去年提供的此答案完全相同:stackoverflow.com/a/56081419/5522000
  • @ArtSchmidt 感谢您的评论:错过了长名单中的那个。我会参考那个答案。
  • .reduce() 的“新”是什么?我想这个评论来自未来,但我认为它在 2020 年也不是什么新鲜事。
  • @VLAZ,不知道为什么我当时写了这个,也许是因为即使在今天还有一些人仍然想支持 IE8,它在那里行不通。我从答案中删除了“新”...
【解决方案9】:

您可以添加一个泛型 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 } } ]
  )

这两个功能可以通过多种方式实现。我选择在oreduce 内附加到Array.prototype.reduce,但您可以轻松地从头开始编写所有内容

【讨论】:

  • 我喜欢你的解决方案,但我不知道它比this one 更清晰/更高效。
  • 这是一个benchmark,表明您的解决方案是最快的。
  • oreduce 中,第一个acc.reduce(acc, k) 中被遮蔽,在ofilter 中,o 被遮蔽——oreduce 被称为o 的变量调用为嗯 - 这是哪个?
  • ofilter 中,变量o 被遮蔽,但它始终指向同一个输入变量;这就是它在这里被遮蔽的原因,因为它是一样的 - 累加器 (acc) 也被遮蔽,因为它更清楚地显示了数据如何通过 lambda 移动; acc 并不总是相同的 binding,但它总是代表我们希望返回的计算结果的当前 persistent 状态
  • 虽然代码运行良好且方法非常好,但我确实想知道编写这样的代码对显然需要 javascript 帮助的人有什么帮助。我只是为了简洁,但这几乎和最小化的代码一样紧凑。
【解决方案10】:

这就是我最近的做法:

const dummyObj = Object.assign({}, obj);
delete dummyObj[key];
const target = Object.assign({}, {...dummyObj});

【讨论】:

  • 嗯。看来您正在混合新旧语法。 Object.assign == ... 你可以写const dummyObj = { ...obj }const target = { ...dummyObj }。另外,后者根本没有必要,因为之后您可以直接使用 dummyObj。
  • 这会复制一个对象的 三个 副本。仅获取其中一个已删除密钥的对象:dummyObj = Object.assign({}, obj) - 将obj 克隆到一个名为dummyObj 的新对象中; delete dummyObj[key]; - 删除密钥。至此你的工作完成了。但随后:{...dummyObj} - 将dummyObj(已经是一个克隆)克隆到一个临时对象中; ` target = Object.assign({}, {...dummyObj})` - 将克隆的临时对象(克隆的克隆)克隆到一个名为 target 的新对象中。
【解决方案11】:

这里的答案绝对是合适的,但它们有点慢,因为它们需要遍历对象中每个属性的白名单。下面的解决方案对于大型数据集来说要快得多,因为它只在白名单中循环一次:

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

const result = sanitize(data, whitelist);

console.log(result);

【讨论】:

    【解决方案12】:

    不使用filter 的更简单的解决方案可以使用Object.entries() 而不是Object.keys() 实现

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

    【讨论】:

      【解决方案13】:

      简单的方法!为此。

      const myData = {
        item1: { key: 'sdfd', value:'sdfd' },
        item2: { key: 'sdfd', value:'sdfd' },
        item3: { key: 'sdfd', value:'sdfd' }
      };
      const{item1,item3}=myData
      const result =({item1,item3})

      【讨论】:

      • 你实际上并没有在这里过滤任何东西,只是解构给定的数据。但是当数据发生变化时会发生什么?
      • @IdrisDopicoPeña - 解构是过滤器。字段名对象与使用字段名数组有何不同? (尽管此解决方案会添加缺少的键)
      • @charles-allen 可以更轻松地更改字段名称数组,而无需更改使用它的代码。因此,您可以拥有一个可重用的函数来获取该数组并过滤您的对象,例如,myFunc(["item1", "item3"]) 稍后可以作为 myFunc(["foo", "bar"]) 重用,而无需更改其工作方式。使用这种方法,您需要为每个要过滤其键的对象使用不同的功能。
      • @VLAZ - 是的。也许我误解了伊德里斯。我认为他们的意思是不同的myData,而不是不同的过滤器(这是我的用例——我知道在编译时我需要什么属性,所以这个解决方案要简单得多)。
      • @charles-allen 我并不是说这个解决方案是错误的。它确实非常有用。但是,问题是有什么区别。如果我需要提取一次item1item3,然后再提取一次foobar,我可能只需要解构两次。如果我需要更频繁地执行此操作,或者我什至不知道我想要哪些,那么我会使用一个函数。
      【解决方案14】:

      捎带ssube's answer

      这是一个可重复使用的版本。

      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 箭头函数的美妙之处在于您不必将allowed 作为参数传入。

      【讨论】:

        【解决方案15】:

        你可以这样做:

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

        【讨论】:

        • 这……太可怕了。我知道with 有它(非常非常少)的用途,但这不是其中之一。它只是通过额外的步骤进行解构。 source => { with(source){ return {item1, item3} } } 等价于 ({item1, item3}) => ({item1, item3}) which is already an answer
        【解决方案16】:

        我知道这已经有很多答案了并且是一个相当古老的问题。但我只是想出了这个简洁的单行:

        JSON.parse(JSON.stringify(raw, ['key', 'value', 'item1', 'item3']))
        

        这将返回另一个仅具有白名单属性的对象。请注意keyvalue 包含在列表中。

        【讨论】:

        • 喜欢这个!执行速度可能非常快,而且很容易过滤掉一个或多个属性
        • @JanisJansen 序列化和反序列化对象对我来说似乎不是很快。此外,您还会丢失函数、undefinedNaN 或 BigInts 等值。
        【解决方案17】:

        有很多方法可以做到这一点。 accepted answer 使用 Keys-Filter-Reduce 方法,这不是最高效的。

        相反,使用for...in 循环遍历对象的键,或遍历允许的键,然后组合一个新对象的性能提高了约 50%a.

        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
        

        一个。有关简单用例的基准,请参阅jsPerf。结果会因浏览器而异。

        【讨论】:

          【解决方案18】:
          const filteredObject = Object.fromEntries(Object.entries(originalObject).filter(([key, value]) => key !== uuid))
          

          【讨论】:

          • 还有其他答案提供了 OP 的问题,它们是前段时间发布的。发布答案时,请确保添加新的解决方案或更好的解释,尤其是在回答较旧的问题时。
          【解决方案19】:

          基于这两个答案:

          https://stackoverflow.com/a/56081419/13819049
          https://stackoverflow.com/a/54976713/13819049

          我们可以做到:

          const original = { a: 1, b: 2, c: 3 };
          const allowed = ['a', 'b'];
          
          const filtered = Object.fromEntries(allowed.map(k => [k, original[k]]));
          

          哪个更干净更快:

          https://jsbench.me/swkv2cbgkd/1

          【讨论】:

            【解决方案20】:

            我很惊讶没有人提出这个建议。它超级干净,并且非常明确地说明了您要保留哪些键。

            const unfilteredObj = {a: ..., b:..., c:..., x:..., y:...}
            
            const filterObject = ({a,b,c}) => ({a,b,c})
            const filteredObject = filterObject(unfilteredObject)
            

            或者如果你想要一个脏的单衬里:

            const unfilteredObj = {a: ..., b:..., c:..., x:..., y:...}
            
            const filteredObject = (({a,b,c})=>({a,b,c}))(unfilteredObject);
            

            【讨论】:

            【解决方案21】:

            另一种捷径

            function filterByKey(v,keys){
              const newObj ={};
              keys.forEach(key=>{v[key]?newObj[key]=v[key]:''});
              return newObj;
            }
            
            //given
            let obj ={ foo: "bar", baz: 42,baz2:"blabla" , "spider":"man", monkey:true};
            
            //when
            let outObj =filterByKey(obj,["bar","baz2","monkey"]);
            
            //then 
            console.log(outObj);
              //{
              //  "baz2": "blabla",
              //  "monkey": true
              //}

            【讨论】:

              【解决方案22】:

              您可以删除对象上的特定属性

              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;
              

              【讨论】:

                【解决方案23】:

                以下方法将对象和任何属性过滤掉。

                function removeObjectKeys(obj, ...keysToRemove) {
                  let mObject = { ...obj }
                  for (let key of keysToRemove) {
                    const { [String(key)]: _, ...rest } = mObject
                    mObject = { ...rest }
                  }
                  return mObject
                }
                    
                const obj = { 123: "hello", 345: "world", 567: "and kitty" };
                const filtered = removeObjectKeys(obj, 123);
                console.log(filtered);
                
                const twoFiltered = removeObjectKeys(obj, 345, 567);
                console.log(twoFiltered);

                【讨论】:

                • 这会导致 linting 错误,因为 _ 没有在其他任何地方使用,但它仍然非常有创意。
                【解决方案24】:

                上述许多解决方案为raw中的每个键重复调用Array.prototype.includes,这将使解决方案O(n·m)(其中n是对象中的键数,m是对象的长度允许列表)。

                这可以通过使用允许的 Set 来避免,但是遍历 allowed 键并将它们复制到一个最初为空的对象会得到非常简单、可读的代码,即 O(m):

                const raw = {
                  item1: { key: 'sdfd', value:'sdfd' },
                  item2: { key: 'sdfd', value:'sdfd' },
                  item3: { key: 'sdfd', value:'sdfd' }
                };
                
                const allowed = ['item1', 'item3'];
                
                const filtered = {};
                for (const key of allowed) {
                  if (key in raw) filtered[key] = raw[key];
                }
                
                console.log(filtered);

                如果您想避免复制继承的属性,也可以使用 raw.hasOwnProperty(key) 代替 key in raw

                【讨论】:

                  【解决方案25】:

                  好的,这个怎么样:

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

                  【讨论】:

                    【解决方案26】:

                    此函数将根据键列表过滤对象,它比上一个答案更有效,因为它不必在调用 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
                        }
                      }, {})
                    }
                    

                    【讨论】:

                      【解决方案27】:

                      在循环期间,遇到某些属性/键时不返回任何内容,然后继续其余的:

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

                      【讨论】:

                        【解决方案28】:

                        另一种方法是使用Array.prototype.forEach()

                        const raw = {
                          item1: {
                            key: 'sdfd',
                            value: 'sdfd'
                          },
                          item2: {
                            key: 'sdfd',
                            value: 'sdfd'
                          },
                          item3: {
                            key: 'sdfd',
                            value: 'sdfd'
                          }
                        };
                        
                        const allowed = ['item1', 'item3', 'lll'];
                        
                        var finalObj = {};
                        allowed.forEach(allowedVal => {
                          if (raw[allowedVal])
                            finalObj[allowedVal] = raw[allowedVal]
                        })
                        console.log(finalObj)

                        它仅包含原始数据中可用的那些键的值,从而防止添加任何垃圾数据。

                        【讨论】:

                          【解决方案29】:

                          这将是我的解决方案:

                          const filterObject = (obj, condition) => {
                              const filteredObj = {};
                              Object.keys(obj).map(key => {
                                if (condition(key)) {
                                  dataFiltered[key] = obj[key];
                                }
                              });
                            return filteredObj;
                          }
                          

                          【讨论】:

                            【解决方案30】:

                            使用PropPick

                            
                            pick('item1 item3', obj);
                            // {
                            //   item1: { key: 'sdfd', value:'sdfd' },
                            //   item3: { key: 'sdfd', value:'sdfd' }
                            // }
                            
                            

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 2017-09-22
                              • 2010-09-25
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2013-07-21
                              相关资源
                              最近更新 更多