【问题标题】:Javascript Filter Non-Array JSON ObjectJavascript 过滤非数组 JSON 对象
【发布时间】:2019-10-07 11:16:51
【问题描述】:

我正在尝试将非数组 JSON 对象过滤为以下 sn-p

const filter = { filterRows: ['one'] };

const templateMapper = {
  'one': {
    title: 'one',
  },
  'two': {
    title: 'two',
  },
  'three': {
    title: 'three',
  },
}

const filterDialogView = filter.filterRows;
const filterTemplateMapper = [templateMapper].filter(row => !filterDialogView.includes(row));
console.log(filterTemplateMapper);

但它没有过滤

我得到以下输出

[
  {
    "one": {
    "title": "one"
  },
  "two": {
    "title": "two"
  },
  "three": {
    "title": "three"
  }
 }
]

渴望输出

 {
  "two": {
    "title": "two"
  },
  "three": {
    "title": "three"
  }
 }

我想根据 filterRows 过滤行,例如,如果 filterRows 包含 one 如上所述 JSON,则应从 templateMapper 中删除 one

【问题讨论】:

  • JSON 在哪里?我所看到的只是一个对象......并且无法使用 Array.filter 过滤对象,因为对象没有过滤方法
  • 我正在使用 [templateMapper] 参见上面的代码我使用了 [] 数组
  • 是的,但是该数组有一个条目 - 整个对象

标签: javascript node.js json filter


【解决方案1】:

一种选择是创建templateMapper 对象的副本,然后遍历filterRows 并删除每个关联的键:

const filter = {
  filterRows: ['one']
};

const templateMapper = {
  'one': {
    title: 'one',
  },
  'two': {
    title: 'two',
  },
  'three': {
    title: 'three',
  },
};


const filterTemplateMapper = { ...templateMapper };
filter.filterRows.forEach((key) => {
  delete filterTemplateMapper[key];
});
console.log(filterTemplateMapper);

(另外,作为评论说明,There's no such thing as a "JSON Object"

【讨论】:

  • 这会改变对象而不是创建新对象,这与过滤器方法的工作方式不同。
  • 它不会改变原始对象 - { ...templateMapper } 创建一个副本。
【解决方案2】:

你可以先filter对象的entries。然后使用Object.fromEntries() 从这些过滤的条目中创建一个新对象。

const filter = { filterRows: ['one'] };

const templateMapper = {
  'one': {
    title: 'one',
  },
  'two': {
    title: 'two',
  },
  'three': {
    title: 'three',
  },
}

const filteredObject = Object.fromEntries(
    Object.entries(templateMapper).filter(([k]) => !filter.filterRows.includes(k))
)

console.log(filteredObject)

【讨论】:

    【解决方案3】:

    您可以filter() 对象。您应该 filter() 对象的条目,然后使用 Object.fromEntries() 再次将其转换为对象

    const filter = { filterRows: ['one'] };
    
    const templateMapper = { 'one': { title: 'one', }, 'two': { title: 'two', }, 'three': { title: 'three', }, }
    
    const filterDialogView = filter.filterRows;
    const filterTemplateMapper = Object.fromEntries(
                 Object.entries(templateMapper)
                       .filter(row => !filterDialogView.includes(row[0].title))
                 );
    console.log(filterTemplateMapper);

    如果您的浏览器不支持Object.fromEntries(),请使用reduce()

    const filter = { filterRows: ['one'] };
    
    const templateMapper = { 'one': { title: 'one', }, 'two': { title: 'two', }, 'three': { title: 'three', }, }
    
    const filterDialogView = filter.filterRows;
    const filterTemplateMapper = Object.entries(templateMapper)
                       .filter(row =>!filterDialogView.includes(row[0].title))
                       .reduce((ac,[k,v]) => (ac[k] = v,ac),{});
    console.log(filterTemplateMapper);

    【讨论】:

      【解决方案4】:

      您可以使用Object.fromEntries 从过滤后的条目中构建对象

      这里的想法是:-

      • 首先从模板对象中获取条目
      • 根据过滤器值过滤条目
      • 使用 Object.fromEntries 从过滤的条目构建对象

      const filter = { filterRows: ['one'] };
      
      const template = {'one': {title: 'one',},'two': {title: 'two',},'three': {title: 'three',}}
      
      const filterDialogView = filter.filterRows;
      const final = Object.entries(template).filter(([row])=> !filterDialogView.includes(row))
      console.log(Object.fromEntries(final));

      如果你的环境不支持 Object.fromEntries 你可以使用这个

      const filter = { filterRows: ['one'] };
      
      const template = {'one': {title: 'one',},'two': {title: 'two',},'three': {title: 'three',}}
      
      const filterDialogView = filter.filterRows;
      const final = Object.entries(template).filter(([row])=> !filterDialogView.includes(row))
      
      const output = final.reduce((op,[key,value])=>{
        op[key] = value
        return op
      },{})
      console.log(output);

      【讨论】:

      • 这是最佳答案(我将发布相同的代码) - 我也会添加一些关于Object.fromEntries 的评论
      • @JaromandaX 谢谢队友 :) 我添加了一些关于代码和相关链接的描述,
      • @CodeManiac 我收到此错误 Object.fromEntries is not a function in Node.JS
      • @user11229655 你用的是哪个版本的节点?
      • @CodeManiac 我在 REPL.it 中尝试过的节点版本似乎与 v10.15.2 有问题。还尝试对其工作正常做出反应,谢谢
      【解决方案5】:

      不要修改原始对象,而是创建它的副本并删除不需要的键。对于删除,您可以使用 delete 关键字。迭代filterRows数组,然后使用delete从复制的对象中删除键

      const filter = {
        filterRows: ['one']
      };
      
      const templateMapper = {
        'one': {
          title: 'one',
        },
        'two': {
          title: 'two',
        },
        'three': {
          title: 'three'
        },
      }
      
      
      let newObj = JSON.parse(JSON.stringify(templateMapper));
      filter.filterRows.forEach(function(item) {
        if (newObj.hasOwnProperty(item)) {
          delete newObj[item]
        }
      });
      console.log(newObj)

      【讨论】:

        【解决方案6】:

        filter() 函数仅适用于数组。为了获得与对象相同的行为,您需要使用对象的entries()

        const filter = {
          filterRows: ['one']
        }
        
        const templateMapper = {
          'one': {
            title: 'one',
          },
          'two': {
            title: 'two',
          },
          'three': {
            title: 'three',
          },
        }
        
        const filteredMapper = Object.entries(templateMapper).reduce((acc, [key, value]) => {
          // if the key is not in the filtered list, add this entry to the object
          if (!filter.filterRows.includes(key)) {
            acc[key] = value
          }
        
          return acc
        }, {}) // pass in empty object as initial value of accumulator
        
        console.log(filteredMapper)

        它的工作方式是我们首先从templateMapper 获取entries(键/值对)。然后我们将这些条目和reduce 他们。 reduce 需要几个参数,包括一个“累加器”,它收集我们想要保留的字段。我们“解构”keyvalue,以便我们可以检查密钥是否在过滤器列表中。如果它不被过滤,我们将它添加到累加器中。然后我们返回累加器以进行reduce的下一次迭代。最后,我们传入一个空对象作为第一次迭代时累加器的初始值。

        【讨论】:

          【解决方案7】:

          你可以这样使用:

          const filter = { filterRows: ['one'] };
          
          const templateMapper = {
            'one': {
              title: 'one',
            },
            'two': {
              title: 'two',
            },
            'three': {
              title: 'three',
            },
          }
          
          // Convert object templateMapper to array with key
          const keyArrayTemplateMapper = Object.keys(templateMapper);
          
          // Filter key array
          const filterKey = keyArrayTemplateMapper.filter(key => !filter.filterRows.includes(key));
          
          // Using reduce method to return new array
          const output = filterKey.reduce((obj, key) => {
              obj[key] = templateMapper[key];
              return obj;
            }, {});
          
          console.log(output);

          【讨论】:

          • 这里的所有答案都被否决了,除了一个。尝试添加代码解释。
          • 我看不出你的代码有什么问题,唯一缺少的是一些解释伙伴,在你的答案中添加解释被认为是一种好习惯,因为这将有助于未来的读者
          • 我明白了,添加了一些解释。谢谢你们。
          • @Scofield 你可以把你的代码做成可执行代码sn-p read here,详细回答你的奖励来了
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-11-15
          • 1970-01-01
          • 2019-12-02
          • 1970-01-01
          • 2023-04-09
          • 2019-10-02
          相关资源
          最近更新 更多