Недавно я преобразовал некоторый код, который использовал обычные объекты в качестве карт, в новый класс es6 Map. Я столкнулся с проблемой довольно быстро, поскольку класс Map включает в себя forEach подобно Array, в него не входит some вместе со многими другими методами Array.prototype.

Чтобы дать некоторый контекст, оригинальный код с обычными объектами JS выглядел примерно так:

var map = {
    entry1: 'test',
    entry2: 'test2'
};

Object.keys(map).some(key => {
    var value = map[key];
    // Do something...found a match
    return true;
});

Класс Map включает в себя entries, но, к сожалению, он возвращает Iterator объект. Это также не включает простой способ доступа к методам Array.prototype.

Мне любопытно, есть ли чистый способ сделать это, или я лаю не на том дереве.

7
KhalilRavanna 9 Янв 2017 в 01:07

3 ответа

Лучший ответ

Используйте Map#values получить итератор значений и {{X1 }} или Array#from (вопрос стиля) для преобразования итератора в массив:

const map = new Map([['a', 1], ['b', 2], ['c', 3]]);

const result = [...map.values()].some((value) => value > 2);

console.log(result);

Как отмечено в @Paulpro комментарий вы можете использовать тот же метод для итерации Map#entries и Map#keys. Например, используя Array#reduce для преобразования карты в объект. Поскольку Array#from вызывает Map#entries, нам не нужно вызывать его явно:

const map = new Map([['a', 1], ['b', 2], ['c', 3]]);

const result = Array.from(map.entries()).reduce((obj, [key, value]) => {
  obj[key] = value;
  return obj;
}, {});

console.log(result);
4
Community 23 Май 2017 в 12:33

Кажется, что самый простой способ решить эту проблему - это какой-то способ преобразовать записи Map в Array, но я не нашел чистого способа сделать это. В настоящее время мое решение в том же духе состоит в том, чтобы определить метод, подобный этому, для выполнения преобразования:

mapEntriesAsArray (map) {
    const entries = [];
    map.forEach((entry, type) => entries.push([type, entry]));
    return entries;
}

Возможно, я мог бы добавить это к Map.prototype, но это выглядит довольно странно, и я уверен, что мне придется бороться с TypeScript, добавив файл d.ts или что-то еще, чтобы он работал без ошибок.

0
KhalilRavanna 8 Янв 2017 в 22:09

Вызвать Array.from объекта Map и вызвать some для этого:

Array.from(map).some(([key, value]) => /* something */ true)

Конечно, это ужасно неэффективно. Гораздо лучшая идея - определить функцию some, которая выполняет , работает на любом итераторе, например, предоставляемом Map:

function some(it, pred) {
    for (const v of it)
        if (pred(v))
            return true;
    return false;
}

some(map.values(), value => /* something */ true)
1
Bergi 8 Янв 2017 в 22:22