2016-08-25 2 views
1

У меня есть массив объектов, как это:Фильтрация массив объектов - несколько критериев

var data = [ 
     { 
      name: "block", 
      sameid: 500, 
      parentid: 62 
     }, 
     { 
      name: "circle", 
      sameid: 500, 
      parentid: 62 
     }, 
     { 
      name: "cube", 
      sameid: 500, 
      parentid: 62 
     }    
    ] 

Мне нужно сделать фильтр на этот массив, чтобы удалить объекты, которые имеют sameid и тот же ParentID , Но вот поворот, который беспокоит меня ... Если я получаю этот массив объектов:

var data = [ 
     { 
      name: "block", 
      sameid: 500, 
      parentid: 62 
     }, 
     { 
      name: "circle", 
      sameid: 500, 
      parentid: 62 
     }, 
     { 
      name: "cube", 
      sameid: 500, 
      parentid: 62 
     }, 
     { 
      name: "grain", 
      sameid: 500, 
      parentid: 63 
     } 
    ] 

Вы можете увидеть, что объект с именем зерном (последним), он имеет различную ParentID. если это так, то ничего не нужно удалять.

Я ломаю голову вокруг этого. Первые критерии, которые я должен учитывать, являются одинаковыми. Я должен их сгруппировать. Затем как-то проверьте наличие идентификаторов родителей.

Массив может содержать множество различных sameid-х и ParentID в

UPDATE: В первом случае, когда данные есть три объекта. Все должны быть удалены, потому что все они имеют одинаковые одинаковые и родительские.

Во втором случае, когда данные имеют четыре объекта, все четыре должны быть сохранены, так как существует один другой объект с разным родителем.

UPDATE Желаемый результат:

var filteredObjects = []; 
    data = [ 
     { 
      name: "block", 
      sameid: 500, 
      parentid: 62 
     }, 
     { 
      name: "circle", 
      sameid: 500, 
      parentid: 62 
     }, 
     { 
      name: "cube", 
      sameid: 500, 
      parentid: 62 
     }, 
     { 
      name: "grain", 
      sameid: 500, 
      parentid: 63 
     } 
    ] 

В этом случае filteredObject будет иметь все значения, так как есть одна другая ParentId:

filteredObjects [{ 
     name: "block", 
     sameid: 500, 
     parentid: 62 
    }, 
    { 
     name: "circle", 
     sameid: 500, 
     parentid: 62 
    }, 
    { 
     name: "cube", 
     sameid: 500, 
     parentid: 62 
    }, 
    { 
     name: "grain", 
     sameid: 500, 
     parentid: 63 
    }] 

В этом случае:

var filteredObjects = []; 
    data = [ 
     { 
      name: "block", 
      sameid: 500, 
      parentid: 62 
     }, 
     { 
      name: "circle", 
      sameid: 500, 
      parentid: 62 
     }, 
     { 
      name: "cube", 
      sameid: 500, 
      parentid: 62 
     }    
    ] 

filterObject не будет иметь значений. Массив данных также может содержать разные аналоги.

+6

Можете ли вы показать желаемый результат? –

+2

У вас есть какой-либо код, который вы пробовали? – Xotic750

+0

Я все еще пытаюсь понять, как это сделать ... мне ничего не приходит в голову :( –

ответ

3

Вы можете построить дерево с sameid и parentid. Затем отфильтруйте элементы и верните только тех, у кого есть два или более parenid.

function filter(array) { 
 
    var hash = {}; 
 
    array.forEach(function (a) { 
 
     hash[a.sameid] = hash[a.sameid] || {}; 
 
     hash[a.sameid][a.parentid] = true; 
 
    }); 
 
    return array.filter(function (a) { 
 
     return Object.keys(hash[a.sameid]).length > 1; 
 
    }); 
 
} 
 

 
var data0 = [{ name: "block", sameid: 500, parentid: 62 }], 
 
    data1 = [{ name: "block", sameid: 500, parentid: 62 }, { name: "circle", sameid: 500, parentid: 62 }, { name: "cube", sameid: 500, parentid: 62 }], 
 
    data2 = [{ name: "block", sameid: 500, parentid: 62 }, { name: "circle", sameid: 500, parentid: 62 }, { name: "cube", sameid: 500, parentid: 62 }, { name: "grain", sameid: 500, parentid: 63 }], 
 
    data3 = [{ name: "block", sameid: 500, parentid: 62 }, { name: "circle", sameid: 500, parentid: 62 }, { name: "cube", sameid: 500, parentid: 62 }, { name: "grain", sameid: 500, parentid: 63 }, { name: "library", sameid: 600, parentid: 66 }, { name: "wood", sameid: 600, parentid: 66 }, { name: "water", sameid: 700, parentid: 77 }, { name: "fire", sameid: 700, parentid: 78 }, { name: "orphan", sameid: 300, parentid: 12 }]; 
 

 
console.log(filter(data0)); 
 
console.log(filter(data1)); 
 
console.log(filter(data2)); 
 
console.log(filter(data3));
.as-console-wrapper { max-height: 100% !important; top: 0; }

+0

Возможно, вы можете использовать 'some', поэтому вам не нужно проверять каждый элемент, если есть разница. – Xotic750

+0

все работы как некоторые. он заканчивается, если возвращаемое значение «false». –

+0

Действительно, не думал так ясно. :) – Xotic750

2

Вы можете использовать Set структуру ES2015, чтобы выяснить, есть ли у вас более чем один вид:

const parentIdSet = new Set(data.map(item => item.parentid)); 
console.log(parentIdSet.size); 
// If 1, you only have one parentId in the entire dataset. 

A Заданная представляет собой набор уникальных значений. Поместив все родительские идентификаторы в набор, все дублирующиеся значения удаляются, и у вас остались только уникальные значения. Если размер Set равен 1, это означает, что у вас есть только один родитель во всем наборе данных.

Использование набора означает, что вы можете избежать необходимости хранить начальные значения где-нибудь и попытаться сравнить. Набор делает это для вас автоматически и с лучшей производительностью (возможно)

+0

Здесь есть хорошая концепция, но это само по себе не решает весь вопрос, так как он не учитывает 'sameid'. – Xotic750

+0

Это руководящий принцип. То же самое можно сделать для' sameid'. –

+0

Действительно, я просто указывал, что это не полное решение и просто аккуратный руководящий принцип и, следовательно, +1. :) – Xotic750

2

Вы можете просто итерацию через исходный массив и построить новую, проверяя уникальность.
Это может быть сделано путем использования Array.prototype.filter:

var data = [ 
 
    { 
 
    name: "same sameid and parentid", 
 
    sameid: 500, 
 
    parentid: 62 
 
    }, 
 
    { 
 
    name: "same sameid and parentid", 
 
    sameid: 500, 
 
    parentid: 62 
 
    }, 
 
    { 
 
    name: "different sameid, same parentid", 
 
    sameid: 501, 
 
    parentid: 62 
 
    }, 
 
    , 
 
    { 
 
    name: "same sameid, different parentid", 
 
    sameid: 500, 
 
    parentid: 63 
 
    } 
 
]; 
 

 
var set = {}; 
 
var newData = data.filter(function(x) { 
 
    var key = x.sameid + "_" + x.parentid; 
 
    
 
    if (set[key]) 
 
    return false; 
 
    
 
    return (set[key] = true); 
 
}); 
 

 
console.log(newData);

Обратите внимание, что этот алгоритм принимает каждое первое вхождение одинаковых идентификаторов. Если вам нужно, вы можете реализовать другую логику.

+1

Когда у вас есть 'newData.push()' внутри 'forEach', вы почти наверняка делаете это неправильно. См. '[] .filter()' и '[] .map()' и '[] .reduce()'. –

+0

@MadaraUchiha Спасибо за ваш комментарий. Обычно я использую эти функции и собираюсь использовать «Array.prototype.every' в своем ответе. Тем не менее, я предпочитал '.forEach', потому что в этом специальном случае он делает код более понятным и понятным **, что более важно на мой взгляд :) –

+0

@MadaraUchiha Я решил обновить свой ответ с помощью' [] .filter() 'решение :) Пожалуйста, проверьте это. –

0

вы можете попробовать это

var distincts = [] 
for (var i = 0; i < data.length; i++) 
    if (distincts.indexOf(data[i].sameid)==-1) 
     distincts.push(data[i].sameid); 

if(distincts.length==1){ 
    var distinctp = [] 
    for (var i = 0; i < data.length; i++) 
     if (distinctp.indexOf(data[i].sameid)==-1) 
      distinctp.push(data[i].sameid); 
    if(distincts.length==1){ 
     data.splice(0,data.length) 
    } 
} 
0

я пытался решить вопрос, вам нужно добавить underscorejs для следующего кода.

var data2 = [ 
    { 
     name: "block", 
     sameid: 500, 
     parentid: 62 
    }, 
    { 
     name: "circle", 
     sameid: 500, 
     parentid: 62 
    }, 
    { 
     name: "cube", 
     sameid: 500, 
     parentid: 62 
    }, 
    { 
     name: "grain", 
     sameid: 500, 
     parentid: 63 
    } 
] 

var backup = data2; 
var count1 = 0; 
var count2 = 0; 
for(var i = 0; i< data2.length ;i ++){ 
    for(var j = i+1;j<data2.length ;j++){ 
    if(data2[i].sameid == data2[j].sameid && data2[i].parentid == data2[j].parentid){ 
     count1++; 
    } 
    else if((data2[i].sameid == data2[j].sameid && data2[i].parentid != data2[j].parentid) ||(data2[i].sameid != data2[j].sameid && data2[i].parentid == data2[j].parentid)){ 
     count2++; 
    } 

    } 
    if(count2 == 0 && count1 != 0){ 
    backup = _.reject(backup,function(d){return d.sameid == data2[i].sameid && d.parentid == data2[i].parentid }) 
    } 
    count2=0;count1=0; 

} 


console.log(backup,"my new array") 
0

Вы также можете посмотреть в этот подход:

data.reduce(function(p, c, index){   
    if (p.length !== index) return [];        

    if (p.length === 0) { 
     return p.concat(c); 
    } 
    else if (p[0].sameid === c.sameid && p[0].parentid === c.parentid){        
      return p.concat(c); 
    }   

     return []; 
    }, []); 
Смежные вопросы