根据数组的多个peoperties

时间:2018-04-03 12:44:55

标签: javascript arrays json iteration

我有一系列元素如下

实体

[
  {
    "name":"tiger",
    "imageurl":"https://someurl.com",
    "type":"animal"
  },
  {
    "name":"cat",
    "imageurl":"https://someurl.com",
    "type":"animal"
  },
{
    "name":"parrot",
    "imageurl":"https://someurl.com",
    "type":"bird"
  },{
    "name":"potato",
    "imageurl":"https://someurl.com",
    "type":"vegetable"
  },
  {
    "name":"orange",
    "imageurl":"https://someurl.com",
    "type":"fruit"
  },
  {
    "name":"orange",
    "imageurl":"https://someurl.com",
    "type":"colour"
  }
]

我有另一个数组如下

elemToRemove

[orange@fruit,cat@animal,tiger@animal]

我想删除包含name=orangetype=fruitname=cattype=animalname=tigertype=animal

的元素

通过在数组上使用过滤器可以很容易地删除基于单个属性的元素,但在这种情况下,我无法使用map / filter / reduce来删除这些元素。

我使用split来创建一个名称和类型数组并试图这样做但是因为我们重复了这个条件总是返回false。

 let nameArray = elemToRemove.map(function (elem) {
    return elem.split('@')[0];
  });

  let typeArray= elemToRemove.map(function (elem) {
    return elem.split('@')[1];
  });

  var reqData= entities.filter(function (obj) {
    return (nameArray.indexOf(obj.name) === -1 && typeArray.indexOf(obj['env']) === -1);
  }); 

因此总是给我一个空的reqData数组。我没有提供id的规定,否则我可以使用id删除元素。

预期输出

[
    {
        "name":"parrot",
        "imageurl":"https://someurl.com",
        "type":"bird"
      },{
        "name":"potato",
        "imageurl":"https://someurl.com",
        "type":"vegetable"
      },
      {
        "name":"orange",
        "imageurl":"https://someurl.com",
        "type":"colour"
      }
    ]

实现这一目标最优雅的方法是什么?

4 个答案:

答案 0 :(得分:4)

Map对于sublinear价值检索的奖励这类问题往往有用。



// Input.
const input = [{"name":"tiger","imageurl":"https://someurl.com","type":"animal"},{"name":"cat","imageurl":"https://someurl.com","type":"animal"},{"name":"parrot","imageurl":"https://someurl.com","type":"bird"},{"name":"potato","imageurl":"https://someurl.com","type":"vegetable"},{"name":"orange","imageurl":"https://someurl.com","type":"fruit"},{"name":"orange","imageurl":"https://someurl.com","type":"colour"}]

// Tags.
const tags = ["orange@fruit", "cat@animal", "tiger@animal"]

// Clean.
const clean = (array, tags) => {
  const map = new Map(array.map(x => [`${x.name}@${x.type}`, x])) // Create Map.
  tags.forEach(tag => map.delete(tag)) // Remove each tag from Map.
  return Array.from(map.values()) // Return Array from Map.values().
}

// Output.
const output = clean(input, tags)

// Proof.
console.log(output)




答案 1 :(得分:1)

您可以使用filter()仅选择那些与所需条件不匹配的对象。我们将使用.some()测试每个对象,以查找对象和要检查字符串的数组之间是否存在匹配。



let data = [{"name":"tiger", "imageurl":"https://someurl.com", "type":"animal"}, {"name":"cat", "imageurl":"https://someurl.com", "type":"animal"}, {"name":"parrot", "imageurl":"https://someurl.com", "type":"bird"}, { "name":"potato", "imageurl":"https://someurl.com", "type":"vegetable"}, { "name":"orange", "imageurl":"https://someurl.com", "type":"fruit"}, { "name":"orange", "imageurl":"https://someurl.com", "type":"colour"}];

let arr = ['orange@fruit', 'cat@animal', 'tiger@animal'];

let result = data.filter(o => !arr.some(s => (
    [name, type] = s.split('@'),
    o['name'] === name && o['type'] === type
)));

console.log(result);

.as-console-wrapper { max-height: 100% !important; top: 0; }




<强>文档:

答案 2 :(得分:1)

您可以使用array.filter

var arr = [
  {"name":"tiger","imageurl":"https://someurl.com","type":"animal"},
  {"name":"cat","imageurl":"https://someurl.com","type":"animal"},
  {"name":"parrot","imageurl":"https://someurl.com","type":"bird"},
  {"name":"potato","imageurl":"https://someurl.com","type":"vegetable"},
  {"name":"orange","imageurl":"https://someurl.com","type":"fruit"},
  {"name":"orange","imageurl":"https://someurl.com","type":"colour"}
];

var toRemove = ['orange@fruit', 'cat@animal', 'tiger@animal'];
var filterOut = toRemove.map(e => { 
  var [name, type] = e.split('@');
  return {name, type};
});
arr = arr.filter(e => !filterOut.find(({name, type}) => e.name === name && e.type === type));

console.log(arr);

答案 3 :(得分:1)

如果您对优雅的定义是尽可能少的代码(以避免人为错误),并重新使用已经由其他人创建的元素,我建议使用像Lodash这样的外部库有这个功能。

第一部分,如果有点复杂,因为我离开了一个字符串:

[orange@fruit,cat@animal,tiger@animal]

需要解析,而不是像其他答案一样已经有一个值数组。

// First we need to convert the filter to a proper Json representation.
// This is needed since the _.remove function takes a Json object.
// This could be simplified if your filter string were already a
// Json object.
var filter = "[orange@fruit,cat@animal,tiger@animal]";
filter = filter.replace(/(\w+)@(\w+)[,\]]/g, (m, p1, p2, offset, string) => {
    return `{"name":"${p1}","type":"${p2}"}${m.includes(']')?']':','}`;
});
filter = JSON.parse(filter);


// Next, apply the filter to the remove function from Lodash.
// Once you have a Json object, it's only two lines of code.
const rm = _.partial(_.remove, obj);
filter.forEach(rm)

var obj = [
  {
    "name":"tiger",
    "imageurl":"https://someurl.com",
    "type":"animal"
  },
  {
    "name":"cat",
    "imageurl":"https://someurl.com",
    "type":"animal"
  },
{
    "name":"parrot",
    "imageurl":"https://someurl.com",
    "type":"bird"
  },{
    "name":"potato",
    "imageurl":"https://someurl.com",
    "type":"vegetable"
  },
  {
    "name":"orange",
    "imageurl":"https://someurl.com",
    "type":"fruit"
  },
  {
    "name":"orange",
    "imageurl":"https://someurl.com",
    "type":"colour"
  }
];

// First we need to convert the filter to a proper Json representation.
// This is needed since the _.remove function takes a Json object.
// This could be simplified if your filter string were already a
// Json object.
var filter = "[orange@fruit,cat@animal,tiger@animal]";
filter = filter.replace(/(\w+)@(\w+)[,\]]/g, (m, p1, p2, offset, string) => {
    return `{"name":"${p1}","type":"${p2}"}${m.includes(']')?']':','}`;
});
filter = JSON.parse(filter);


// Next, apply the filter to the remove function from Lodash.
// Once you have a Json object, it's only two lines of code.
const rm = _.partial(_.remove, obj);
filter.forEach(rm)

console.log(obj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>