Estou tentando usar o novo objeto Map do Javascript EC6, pois ele já é suportado nas versões mais recentes do Firefox e Chrome.
Mas estou achando isso muito limitado na programação "funcional", porque carece de métodos clássicos de mapa, filtro etc. que funcionariam bem com um [key, value]
par. Ele tem um forEach, mas que NÃO retorna o resultado do retorno de chamada.
Se eu pudesse transformar seu map.entries()
MapIterator em um Array simples, poderia usar o padrão .map
, .filter
sem hacks adicionais.
Existe uma maneira "boa" de transformar um iterador Javascript em uma matriz? Em python é tão fácil quanto fazer list(iterator)
... mas Array(m.entries())
retorne uma matriz com o Iterator como seu primeiro elemento !!!
EDITAR
Esqueci de especificar que estou procurando uma resposta que funcione onde quer que o Map funcione, o que significa pelo menos Chrome e Firefox (o Array.from não funciona no Chrome).
PS.
Eu sei que há o fantástico wu.js, mas sua dependência do traceur me deixa desconfortável ...
fonte
Respostas:
Você está procurando a nova
Array.from
função que converte iterables arbitrários em instâncias de array:Agora é suportado no Edge, FF, Chrome e Node 4+ .
Claro, pode valer a pena para definir
map
,filter
e métodos semelhantes diretamente na interface do iterador, para que você possa evitar a alocação da matriz. Você também pode usar uma função de gerador em vez de funções de ordem superior:fonte
(value, key)
pares e não(value, index)
pares.yourTransformation = function([key, value], index) { … }
Map
possui pares de valores de chave. Portanto, na minha humilde opinião, não faz sentido definir geralmap
efilter
funções para iteradores. Em vez disso, cada objeto iterable deve ter seu própriomap
efilter
funções. Isso faz sentido porquemap
efilter
são operações de preservação da estrutura (talvez não,filter
masmap
certamente é) e, portanto, as funçõesmap
efilter
devem conhecer a estrutura dos objetos iteráveis que eles estão mapeando ou filtrando. Pense bem, em Haskell definimos diferentes instâncias deFunctor
. =)[...map.entries()]
ouArray.from(map.entries())
É super fácil.
Enfim - os iteradores não têm métodos de redução, filtro e similares. Você precisa escrevê-las por conta própria, pois é mais eficiente do que converter o Mapa em array e vice-versa. Mas não faça saltos Mapa -> Matriz -> Mapa -> Matriz -> Mapa -> Matriz, porque isso prejudicará o desempenho.
fonte
Array.from
já foi coberto pelo @Bergi.[iterator]
não funciona porque no Chrome ele cria um array com um únicoiterator
elemento nele, e[...map.entries()]
não é uma sintaxe aceito no ChromeNão há necessidade de transformar um
Map
em umArray
. Você pode simplesmente criarmap
efilter
funções paraMap
objetos:Por exemplo, você pode acrescentar um estrondo (ou seja,
!
caractere) ao valor de cada entrada de um mapa cuja chave seja primitiva.Você também pode adicionar
map
efilter
métodos sobreMap.prototype
a fazê-lo ler melhor. Embora geralmente não seja aconselhável modificar protótipos nativos, acredito que uma exceção possa ser feita no caso demap
efilter
paraMap.prototype
:Edit: Na resposta de Bergi, ele criou funções genéricas
map
efilter
geradoras para todos os objetos iteráveis. A vantagem de usá-los é que, como são funções geradoras, eles não alocam objetos iteráveis intermediários.Por exemplo, minhas funções
map
efilter
definidas acima criam novosMap
objetos. Portanto, a chamadaobject.filter(primitive).map(appendBang)
cria dois novosMap
objetos:Criar objetos iteráveis intermediários é caro. As funções de gerador da Bergi resolvem esse problema. Eles não alocam objetos intermediários, mas permitem que um iterador alimente seus valores lentamente para o próximo. Esse tipo de otimização é conhecido como fusão ou desmatamento em linguagens de programação funcionais e pode melhorar significativamente o desempenho do programa.
O único problema que tenho com as funções geradoras de Bergi é que elas não são específicas para
Map
objetos. Em vez disso, eles são generalizados para todos os objetos iteráveis. Portanto, em vez de chamar as funções de retorno de chamada com(value, key)
pares (como seria de esperar ao mapear sobre aMap
), ele chama as funções de retorno de chamada com(value, index)
pares. Caso contrário, é uma excelente solução e eu recomendaria definitivamente usá-lo sobre as soluções que forneci.Portanto, estas são as funções específicas do gerador que eu usaria para mapear e filtrar
Map
objetos:Eles podem ser usados da seguinte maneira:
Se você deseja uma interface mais fluente, pode fazer algo assim:
Espero que ajude.
fonte
Map
objetos usando funçõesmap
efilter
funções especializadas . A resposta de Bergi demonstra o uso de funçõesmap
e genéricosfilter
para todos os objetos iteráveis que não podem ser usados para transformarMap
objetos porque as chaves doMap
objeto estão perdidas.Array.from
ela não funciona no Chrome (enquanto o Map e os iteradores funcionam!). Mas posso ver que a abordagem é muito semelhante e você pode adicionar a função "toArray" ao seu grupo!toArray
função.Uma pequena atualização de 2019:
Agora Array.from parece estar disponível universalmente e, além disso, aceita um segundo argumento mapFn , que impede a criação de uma matriz intermediária. Isso basicamente se parece com isso:
fonte
Array.from
já existe uma resposta , isso é mais adequado para ser um comentário ou uma edição solicitada para essa resposta ... mas obrigado!Você pode usar uma biblioteca como https://www.npmjs.com/package/itiriri que implementa métodos de matriz para iterables:
fonte
Você pode obter a matriz de matrizes (chave e valor):
E então, você pode facilmente obter valores de dentro, como por exemplo as chaves com o iterador do mapa.
fonte
Você também pode usar fluentemente iterável para transformar em matriz:
fonte