2014-10-14 2 views
1
$.each(constructions, function(i,v) { 
if ($.inArray(v.name, map[ii].buildings) == -1) {//stuff} 
}; 

Где constructions - это массив объектов, каждый из которых имеет уникальное имя. map[ii].buildings - это массив, содержащий некоторые из этих объектов. Я хочу итерации каждого объекта в constructions, проверяя, отображается ли его параметр имени в объектах map[ii].buildings.Проверьте, находится ли объект с индексом в массиве

Вышеупомянутый код работает, если каждый элемент массива map[ii].buildings является только текстовой строкой имени объекта, но не если элемент является целым объектом .. закрыть, но не кубик>. <

+0

Будет '$ .grep()' работать лучше для вас, чем '$ .inArray()'? Вы пытаетесь проверить уникальный идентификатор объекта для зданий или у вас есть один и тот же объект в двух разных массивах? – nothingisnecessary

+0

@nothingisnecessary первоначально его одного и того же объекта, но другие значения объекта в зданиях меняются, поэтому он быстро станет другим, но всегда с тем же именем. – user3317592

ответ

2

Попробуйте использовать $.grep() вместо $.inArray(); вы можете указать функцию для фильтрации.

Вместо проверки на -1, то проверить, является ли массив, который $.grep() возвращается имеет length == 0

Простой пример: (будет легче, если вы разместили код/​​пример того, что «конструкции» объекты выглядят)

var constructions = [{ 
 
     Name: "Mess hall", 
 
     SqFt: 5000 
 
    }, { 
 
     Name: "Infirmary", 
 
     SqFt: 2000 
 
    }, { 
 
     Name: "Bungalow", 
 
     SqFt: 2000 
 
    }, { 
 
     Name: "HQ", 
 
     SqFt: 2000 
 
    }]; 
 
    
 
    var buildings = [{ 
 
     Name: "Infirmary", 
 
     SqFt: 2000 
 
    }, { 
 
     Name: "HQ", 
 
     SqFt: 2000 
 
    }]; 
 
    
 
    // found buildings will be list of items in "constructions" that is not in "buildings" 
 
    var foundBuildings = $.grep(constructions, function (constructionsItem) { 
 
     return $.grep(buildings, function (buildingsItem) { 
 
      return buildingsItem.Name === constructionsItem.Name 
 
     }).length == 0; // == 0 means "not in", and > 0 means "in" 
 
    }); 
 
    
 
    // this just renders the results all pretty for ya 
 
    $.each(foundBuildings, function (idx, item) { 
 
     $("#output").append("<div>" + item.Name + "</div>"); 
 
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id='output'></div>

Пример jsFiddle: http://jsfiddle.net/eLeuy9eg/3/

+0

Это выглядит хорошо ... но я должен был быть более ясным, как я могу найти найденные на самом деле объекты в конструкциях, которые НЕ в зданиях? В контексте игра проверяет, существует ли каждое здание в массиве, а если нет, оно перечисляет их. – user3317592

+0

Я думаю, что вы просто передаете 'true' как третий аргумент' $ .grep() ', который инвертирует результаты. См. JQuery docs для grep: http://api.jquery.com/jquery.grep/. И вы, вероятно, захотите переписать конструкцию цикла. – nothingisnecessary

+0

Кажется, что не работает, редактирование, которое я сделал для вашего кода, находится здесь http://jsfiddle.net/eLeuy9eg/2/ - он чувствует себя близко tho>. < – user3317592

0

Не-jQuery способ сделать это будет использовать filter. Что-то вроде этого:

// pass in an array and the key for which you want values 
// it returns an array of those values 
function getValues(arr, key) { 
    return arr.map(function (el) { return el[key]; }); 
} 

function notFoundIn(arr, arr2) { 

    // grab the names of the buildings 
    var buildings = getValues(arr2, 'name'); 

    // grab the names from the construction objects and filter 
    // those that are not in the building array 
    return getValues(arr, 'name').filter(function (el) { 
    return buildings.indexOf(el) === -1; 
    }); 
} 

notFoundIn(constructions, buildings); // eg [ "one", "three" ] 

DEMO

Можно даже добавить новый метод к прототипу массива. С помощью этого вы можете использовать либо простые массивы, либо массивы объектов, если вы передадите ключ. Обратите внимание, в этом примере я заменил map и filter с петлями, которые выполняют ту же функцию, но быстрее (см комментариев):

function getValues(arr, key) { 
    var out = []; 
    for (var i = 0, l = arr.length; i < l; i++) { 
    out.push(arr[i][key]); 
    } 
    return out; 
} 

if (!Array.prototype.notFoundIn) { 
    Array.prototype.notFoundIn = function (inThisArray, key) { 
    var thisArr = key ? getValues(this, key) : this; 
    var arrIn = key ? getValues(inThisArray, key) : inThisArray; 
    var out = []; 
    for (var i = 0, l = thisArr.length; i < l; i++) { 
     if (arrIn.indexOf(thisArr[i]) === -1) { 
     out.push(thisArr[i]); 
     } 
    } 
    return out; 
    } 
} 


constructions.notFoundIn(buildings, 'name'); 
[1, 2, 3].notFoundIn([2]); // [1, 3] 

DEMO

+1

yup, Array.filter() - хороший материал.Второй пример работает нормально, когда ключ не передан, но в противном случае он немного медленнее (http://jsperf.com/setsubtraction). Зачем создавать дополнительные массивы для ключей объекта? Поскольку эти функции возвращают массив строк вместо массива объектов, вызывающему нужно будет искать объект от его ключа в любом случае, правильно? – nothingisnecessary

+0

@nothingisnecessary Спасибо за ответ. Это интересно. Если я исключил 'filter' и' map' и заменил их на простые циклы, упомянутый выше метод замены прототипа [выходит быстрее, чем 'grep'] (http://jsperf.com/setsubtraction/2). – Andy

Смежные вопросы