Поиск в массиве объектов (два свойства) для нескольких ограничений - PullRequest
0 голосов
/ 26 октября 2018

Прежде чем задать вопрос, я прошу прощения за ужасный заголовок, но я не могу описать его лучше.

У меня есть массив объектов, созданных таким образом:

var setitems = new Array();
setitems.push({set: "1000", item: "5000"});
setitems.push({set: "1000", item: "5010"});
setitems.push({set: "1000", item: "5020"});
setitems.push({set: "1000", item: "5050"});
setitems.push({set: "1010", item: "5010"});
setitems.push({set: "1010", item: "5020"});
setitems.push({set: "1010", item: "5030"});
setitems.push({set: "1020", item: "5020"});
setitems.push({set: "1020", item: "5040"});
setitems.push({set: "1020", item: "5041"});
setitems.push({set: "1030", item: "5040"});
setitems.push({set: "1030", item: "5041"});
setitems.push({set: "1030", item: "5030"});
setitems.push({set: "1040", item: "5041"});
setitems.push({set: "1040", item: "5042"});

Предметы и наборы находятся в отношениях многих ко многим.

И простой строковый массив, подобный этому:

var itemlist = new Array();
itemlist.push("5010");
itemlist.push("5020");
// itemlist = ["5010", "5020"];

Мне нужно знать, какие наборы содержат все элементы в списке предметов.

В этом примере он должен возвращать 1000 и 1010.

Количество элементов в наборе является переменным.

Количество элементов в списке элементов является переменным.

Спасибо.

Ответы [ 3 ]

0 голосов
/ 26 октября 2018

Вы можете сделать это с Set экземплярами:

// Get an array of Set instances for entries matching itemlist entries
const [first, ...rest] = itemlist.map(item =>
    setitems.filter(entry => entry.item === item)
            .reduce((s, entry) => s.add(entry.set), new Set())
);
// Get an array of the entries in the first of those Sets that also have entries in all the rest
const result = [...first].filter(set => rest.every(s => s.has(set)));

const setitems = [];
setitems.push({set: "1000", item: "5000"});
setitems.push({set: "1000", item: "5010"});
setitems.push({set: "1000", item: "5020"});
setitems.push({set: "1000", item: "5050"});
setitems.push({set: "1010", item: "5010"});
setitems.push({set: "1010", item: "5020"});
setitems.push({set: "1010", item: "5030"});
setitems.push({set: "1020", item: "5020"});
setitems.push({set: "1020", item: "5040"});
setitems.push({set: "1020", item: "5041"});
setitems.push({set: "1030", item: "5040"});
setitems.push({set: "1030", item: "5041"});
setitems.push({set: "1030", item: "5030"});
setitems.push({set: "1040", item: "5041"});
setitems.push({set: "1040", item: "5042"});

const itemlist = [];
itemlist.push("5010");
itemlist.push("5020");

// Get an array of Set instances for entries matching itemlist entries
const [first, ...rest] = itemlist.map(item =>
    setitems.filter(entry => entry.item === item)
            .reduce((s, entry) => s.add(entry.set), new Set())
);
// Get an array of the entries in the first of those Sets that also have entries in all the rest
const result = [...first].filter(set => rest.every(s => s.has(set)));
console.log(result);
0 голосов
/ 26 октября 2018

Возможное решение может использовать двухэтапный подход.

На первом шаге создается карта / таблица / реестр всех возможных списков "установленных" значений.

Затем выполняется последний шагдает результат.Он создает список идентификаторов «set», в котором каждый связанный список значений «set» содержит каждое значение другого предоставленного списка значений.

Код только для ES5 может выглядеть следующим образом ...

var setItemList = new Array();
setItemList.push({set: "1000", item: "5000"});
setItemList.push({set: "1000", item: "5010"});
setItemList.push({set: "1000", item: "5020"});
setItemList.push({set: "1000", item: "5050"});
setItemList.push({set: "1010", item: "5010"});
setItemList.push({set: "1010", item: "5020"});
setItemList.push({set: "1010", item: "5030"});
setItemList.push({set: "1020", item: "5020"});
setItemList.push({set: "1020", item: "5040"});
setItemList.push({set: "1020", item: "5041"});
setItemList.push({set: "1030", item: "5040"});
setItemList.push({set: "1030", item: "5041"});
setItemList.push({set: "1030", item: "5030"});
setItemList.push({set: "1040", item: "5041"});
setItemList.push({set: "1040", item: "5042"});

var itemlist = new Array();
itemlist.push("5010");
itemlist.push("5020");


// ... with good old ES-5 do ...


// 1st part of solution ... create a map/table/registry of all possible "set" value lists.
//
function collectAndFillSetValueLists (registry, setItem) {
    var key   = setItem.set;
    var value = setItem.item;
    var list  = registry[key] || (registry[key] = []); // get or create a "set" item specific list.

    // if (!list.includes(value)) {
    if (list.indexOf(value) === -1) {

        list.push(value);
    }
    return registry;
}
var setItemsRegistry = setItemList.reduce(collectAndFillSetValueLists, {});

console.log('setItemsRegistry : ', setItemsRegistry);


// 2nd part of solution ... create a list of "set" identifiers where each related
// "set" value list contains every value of another provided value list.
//
function collectSetIdsThatsListsContainEveryValue(collector, setKey) {
    var list = collector.registry[setKey];
    if (collector.valueList.every(function (setValue) {

        return (list.indexOf(setValue) >= 0);
        // return list.includes(setValue);
    })) {
        collector.keyList.push(setKey)
    }
    return collector;
}
var setIdentifierList = Object.keys(setItemsRegistry).reduce(collectSetIdsThatsListsContainEveryValue, {

    registry: setItemsRegistry,
    valueList: itemlist,
    keyList: []

}).keyList;

console.log('setIdentifierList : ', setIdentifierList);
.as-console-wrapper { max-height: 100%!important; top: 0; }
0 голосов
/ 26 октября 2018

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

const setitems = [];
setitems.push({set: "1000", item: "5000"});
setitems.push({set: "1000", item: "5010"});
setitems.push({set: "1000", item: "5020"});
setitems.push({set: "1000", item: "5050"});
setitems.push({set: "1010", item: "5010"});
setitems.push({set: "1010", item: "5020"});
setitems.push({set: "1010", item: "5030"});
setitems.push({set: "1020", item: "5020"});
setitems.push({set: "1020", item: "5040"});
setitems.push({set: "1020", item: "5041"});
setitems.push({set: "1030", item: "5040"});
setitems.push({set: "1030", item: "5041"});
setitems.push({set: "1030", item: "5030"});
setitems.push({set: "1040", item: "5041"});
setitems.push({set: "1040", item: "5042"});

const itemlist = [];
itemlist.push("5010");
itemlist.push("5020");

const find = (arr, list) => {

    const grouped = arr.reduce((acc, val) => ({ ...acc, [val.set]: (acc[val.set] || []).concat(val.item) }), {});

    return Object.keys(grouped).reduce((acc, val) => {
        
        if (list.every(item => grouped[val].includes(item))) acc.push(val);
        
        return acc;
        
    }, []);
};

console.log(find(setitems, itemlist));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...