Получать не соответствующие данные из 2 объектов массива в javascript

rushabh shah спросил: 31 июля 2018 в 09:37 в: javascript

У меня есть массивы, 1 массив - это основные данные и другой массив, который содержит разделенное по каналу значение. пожалуйста, найдите ниже код для того же

var master = [
{id:1, value:'John'},
{id:2, value:'Bobby'}
];var names = [
{id:1, name:'Sandra|John', type:'user', username:'sandraJ'},
{id:2, name:'John', type:'admin', username:'johnny2'},
{id:3, name:'Peter|John', type:'user', username:'peteJ'},
{id:4, name:'Bobby', type:'user', username:'be_bob'},
{id:4, name:'Peter1|John1', type:'user', username:'be_bob'}
];

Результат должен быть следующим

var result3 = [
{id:1, name:'Sandra'},
{id:2, name:'Peter'},
{id:2, name:'Peter1|John1'}
];

Я пробовал следующую версию ES6, но он не бросает ожидаемый результат.

let result = names.filter(o1 => !master.some(o2 => 
o1.name.split('|').includes(o2.value)));

Я также попытался заменить некоторые с каждым, но все же он не работает

let result = names.filter(o1 => !master.every(o2 => 
o1.name.split('|').includes(o2.value)));

может кто-то, пожалуйста, помогите мне с тем же?


4 ответа

Есть решение
Shilly ответил: 31 июля 2018 в 10:03

Это предполагает, что идентификаторы в результате неверны, поскольку я не знаю, как Питер | Джон и Питер1 | Джон1 меняют свои идентификаторы на 2.

const master = [
  {id:1, value:'John'},
  {id:2, value:'Bobby'}
];
const names = [
  {id:1, name:'Sandra|John', type:'user', username:'sandraJ'},
  {id:2, name:'John', type:'admin', username:'johnny2'},
  {id:3, name:'Peter|John', type:'user', username:'peteJ'},
  {id:4, name:'Bobby', type:'user', username:'be_bob'},
  {id:4, name:'Peter1|John1', type:'user', username:'be_bob'}
];
// map the valid names for easier access
const valid_names = master.map(({ value }) => value );
// We could map => filter instead if that's clearer.
const invalid_items = names.reduce(( invalid_items, item ) => {
  // Get all the diferent names inside the item.
  const item_names = item.name.split( '|' );
  // Filter out all the valid names
  const invalid_names = item_names.filter( name => !valid_names.includes( name ));
  // If there are invalid names remaining, create a new object.
  // No idea how the "id" property should be transformed.
  if ( invalid_names.length ) {
    invalid_items.push({
      id: item.id,
      name: invalid_names.join( '|' )
    });
  }
  return invalid_items;
}, [] );
console.log( invalid_items );
rushabh shah ответил: 31 июля 2018 в 12:47
эй спасибо, это решение работает :)
rottenoats ответил: 31 июля 2018 в 09:55

Вот версия с использованием filter и findIndex.

const master = [
  {id:1, value:'John'},
  {id:2, value:'Bobby'}
];

const names = [
  {id:1, name:'Sandra|John', type:'user', username:'sandraJ'},
  {id:2, name:'John', type:'admin', username:'johnny2'},
  {id:3, name:'Peter|John', type:'user', username:'peteJ'},
  {id:4, name:'Bobby', type:'user', username:'be_bob'},
  {id:4, name:'Peter1|John1', type:'user', username:'be_bob'}
];

//This step, if you wish that the original data should not be mutated.
const namesCopy = Object.assign([], names);

//Filter through the names
const result = namesCopy.filter(obj=>{

  //Split the name if there is a |
  const split = obj.name.split("|");

  //Create a new name without the master names in it
  const newName = split.filter(name=>{
    //check to see if the master name exists within the name
    return master.findIndex(obj2=>obj2.value === name) === -1;
  }).join("|"); // Join them together as a string if there is more than one name left
  
  //If newName is empty then we can assume that master names existed in this object
  if(newName.length === 0) return false;
  
  //otherwise update the name with newName
  obj.name = newName;
  return true;
});

console.log(result);
Nina Scholz ответил: 31 июля 2018 в 09:55
это изменяет исходные данные.
rottenoats ответил: 31 июля 2018 в 10:00
@NinaScholz это лучше? Иначе я не знаю, как мне это сделать.
Adriani6 ответил: 31 июля 2018 в 09:57

Как насчет этого?

с использованием .map, .filter и for loop.

var master = [
{id:1, value:'John'},
{id:2, value:'Bobby'}
];

var names = [
{id:1, name:'Sandra|John', type:'user', username:'sandraJ'},
{id:2, name:'John', type:'admin', username:'johnny2'},
{id:3, name:'Peter|John', type:'user', username:'peteJ'},
{id:4, name:'Bobby', type:'user', username:'be_bob'},
{id:4, name:'Peter1|John1', type:'user', username:'be_bob'}
];

let yFilter = master.map(itemY => { return itemY.value; });
let filteredX = names.filter(itemX => !yFilter.includes(itemX.name));

var processed = [];

for(var i = 0; i < filteredX.length; i++){
	var item = filteredX[i];
  var contains = master.filter(function(x){ return item.name.split("|").indexOf(x.value) > -1; });
  
  if(contains.length > 0){
  	item.name = item.name.substring(0, item.name.indexOf(contains[0].value) - 1);
  }
  processed.push(item);
}

console.log(processed);
Nina Scholz ответил: 31 июля 2018 в 10:12

Вы можете сопоставить объекты с отфильтрованными именами и затем фильтровать по длине имен. В конце сопоставьте новые объекты с обновленным свойством name.

var master = [{ id: 1, value: 'John' }, { id: 2, value: 'Bobby' }],
    names = [{ id: 1, name: 'Sandra|John', type: 'user', username: 'sandraJ' }, { id: 2, name: 'John', type: 'admin', username: 'johnny2' }, { id: 3, name: 'Peter|John', type: 'user', username: 'peteJ' }, { id: 4, name: 'Bobby', type: 'user', username: 'be_bob' }, { id: 4, name: 'Peter1|John1', type: 'user', username: 'be_bob' }],
    result = names
        .map((s => o =>
            [o, o.name.split('|').filter(n => !s.has(n)).join('|')]
        )(new Set(master.map(({ value }) => value))))
        .filter(([, { length }]) => length)
        .map(([o, name]) => Object.assign({}, o, { name }));

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