【问题标题】:Select a property from an array of objects based on a value : Javascript根据值从对象数组中选择一个属性:Javascript
【发布时间】:2019-12-03 12:25:01
【问题描述】:

我有一个具有以下结构的对象数组:

var arr = [
  {
    "value": "abc",
    "checked": true
  },
  {
    "value": "xyz",
    "checked": false
  },
  {
    "value": "lmn",
    "checked": true
  }
];

let result = arr.filter(item => item.checked);

console.log(result);

我希望输出是:

["abc", "lmn"] 

因为这两个values 有checked: true

我已经尝试根据检查值过滤掉:

let result = arr.filter(item => item.checked);

我正在获取具有设置为 truechecked 属性值的对象。

我们将不胜感激。

【问题讨论】:

标签: javascript arrays object ecmascript-6


【解决方案1】:

您可以使用reduce 并检查checked 属性是否为真,然后push(正如assoron 所指出的)累加器的值 - 不需要2个循环:

const arr = [
  { "value": "abc", "checked": true },
  { "value": "xyz", "checked": false },
  { "value": "lmn", "checked": true }
]

const filtered = arr.reduce((a, o) => (o.checked && a.push(o.value), a), [])      
console.log(filtered)

【讨论】:

  • @assoron 是的,你是对的。我只写了 concat ,所以你可以把它写在一行上,以便更具可读性。而且传播语法非常慢,我记得曾经写过一个 JSPerf,而 iirc 慢了 50%。
  • @assoron 检查这个性能 jsperf.com/push-vs-concat-with-reduce/1 - 慢 94% 大声笑
  • 我古老的浏览器设置让 concat 慢了 40%。
  • 你可以在一行中使用push:(a.push(o.value), a)
  • 是的 - 逗号运算符评估所有传递的代码,然后使用最后一个。所以a.push(o.value)运行,然后a作为表达式的返回值,从函数中返回。有意义吗?
【解决方案2】:
var a = [];
arr.forEach( (i)=> i.checked ? a.push(i.value) :null  )

它将评估在 foreach 中为数组的每个元素传递的方法,并检查 element.checked 是否为真,它会将 element.value 推送到数组 a 中,这是所需的输出。

【讨论】:

    【解决方案3】:

    您基本上可以同时使用.reducemapfilter。下面我使用[v].slice(+!c) 构建了一个累积数组,如果c 为真,它将将该值添加到(累积)数组中,否则它不会将它添加到数组中(因为[v].slice(+!false) 将返回[],和[...[]] 将给[]):

    const arr = [{
     "value": "abc",
     "checked": true
    }, {
     "value": "xyz",
     "checked": false
    }, {
     "value": "lmn",
     "checked": true
    }];
    
    const res = arr.reduce((a, {value:v, checked:c}) => [...a, ...[v].slice(+!c)], []);
    console.log(res);

    【讨论】:

      【解决方案4】:

      Array.prototype.reduce() 可能会对您有所帮助。 reduce() 回调有两个参数,第一个参数是旧的/先前的迭代值,第二个参数是当前的迭代值/元素。

      因此,使用此函数,我们可以将当前迭代值保持为之前的迭代值(总值)。

      reduce() 方法对数组的每个元素执行(您提供的)reducer 函数,从而产生单个输出值。

      var arr = [{"value": "abc","checked": true},{"value": "xyz","checked": false},{"value": "lmn","checked": true}]
      
      const result = arr.reduce((acc, cur) => ((cur.checked && acc.push(cur.value)), acc), [])
      console.log(result)

      【讨论】:

      • 只返回最后一个(...)
      【解决方案5】:

      您没有推送新数组中的值。试试这个它工作正常。

      const arr = [{ "value": "abc", "checked": true }, { "value": "xyz", "checked": false }, { "value": "lmn", "checked": true }]
      let result = []
      let check = arr.filter((val) => {
          if (val.checked) {
              result.push(val.value)
          }
      })
      console.log(result);
      

      【讨论】:

        【解决方案6】:

        创建一个泛型函数,您只需在其中传递键值和数组,它将过滤掉基本参数的数组

         var arr = [
                  {
                    "value": "abc",
                    "checked": true
                  },
                  {
                    "value": "xyz",
                    "checked": false
                  },
                  {
                    "value": "lmn",
                    "checked": true
                  }
                ]
        
        
                    function filterList(keyValue, list) {
                        let filteredList = [];
                        for(let i = 0; i < list.length; i++) {
                            if(list[i]["checked"] === keyValue) {
                                filteredList.push(list[i]["value"]);
                            }
                        }
                        return filteredList;
                    }
        
            console.log(filterList(true, arr));
        

        【讨论】:

          【解决方案7】:

          这里的所有解决方案都是有效的,但是如果您更喜欢使用 ES6+ 语法的更迭代的方法,您可以显式地对您的项目进行每个循环,以便让您的读者非常清楚您的意图(另外,它比连接 @987654321 更快@ 和 map,因为它会在您的列表中循环两次):

          const items = [
            {
              "value": "abc",
              "checked": true
            },
            {
              "value": "xyz",
              "checked": false
            },
            {
              "value": "lmn",
              "checked": true
            }
          ];
          
          const formattedListOfFilteredItems = [];
          for (item of items) {
            if (item.checked)
              formattedListOfFilteredItems.push(item.value);
          }
          
          console.log(formattedListOfFilteredItems);

          【讨论】:

            【解决方案8】:

            不要把事情复杂化。只需使用普通的 for 循环并保存运行时。即使您的数组中的所有元素都有一个选中的属性true,以下内容也只会迭代一次数组。

            var arr = [{
             "value": "abc",
             "checked": true
            }, {
             "value": "xyz",
             "checked": false
            }, {
             "value": "lmn",
             "checked": true
            }];
            
            var results = [];
            for(var i=0; i<arr.length-1; i++) {
              if(arr[i].checked === true){
                results.push(arr[i].value)
              }
            }

            如果您查看 .map/.filter 的内部实现,他们将使用 while 循环迭代数组。假设您有一个数据,其中所有元素都设置为选中为 true,那么 filter 将遍历所有元素,然后 map 将遍历它们以从中获取值。

            【讨论】:

            • 这就是我使用 reduce 的原因 :) 尽管如此,for 循环在这里更有效。
            • @Kobe 同意...!
            【解决方案9】:

            使用map和filter函数如下:

            var arr = [ {
              "value": "abc",
              "checked": true
            },
            {
              "value": "xyz",
              "checked": false
            },
            {
              "value": "lmn",
              "checked": true
            }]
            
            
            let checkedValues = arr.map((item) => item.checked ? item.value : null).filter(item => item);
            
            console.log(checkedValues);

            【讨论】:

              【解决方案10】:

              使用过滤器和地图:

              const arr =[{"value":"abc","checked":true},{"value":"xyz","checked":false},{"value":"lmn","checked":true}];
              
               const result = arr.filter(res=>res.checked).map(ele=>ele.value);
               
               console.log(result);

              【讨论】:

              • 如果你想要唯一的值: const result = Array.from(new Set(arr.filter(res=>res.checked).map(ele=>ele.value)));跨度>
              【解决方案11】:

              修复数据结构并使用过滤器和映射

              var obj = [  
                          {
                              "value" : "abc",
                              "checked" : true
                          },
                          {
                              "value" : "xyz",
                              "checked" : false
                          },
                          {
                              "value" : "lmn",
                              "checked" : true
                          }
                         ]
              console.log(obj.filter(function(e){return e.checked==true}).map(function(e){return e.value}))

              【讨论】:

              • 你怎么在这里使用旧语法?当它不是 es6 时,它在一行上看起来很奇怪:P
              【解决方案12】:

              首先,这不是有效的 JS - 你需要交换你的括号和大括号。数组使用[],对象使用{},而不是相反。

              其次,你应该先filter根据checked属性取出想要的对象,然后使用map提取你想要的属性:

              const arr =[{"value":"abc","checked":true},{"value":"xyz","checked":false},{"value":"lmn","checked":true}];
              
              const res = arr.filter(({ checked }) => checked).map(({ value }) => value);
              
              console.log(res);

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-01-08
                • 2014-08-04
                • 2017-03-19
                • 2021-10-03
                • 2020-04-20
                • 2019-08-12
                • 2021-11-07
                • 2015-12-07
                相关资源
                最近更新 更多