Eu queria adicionar os elementos de uma matriz em outra, então tentei o seguinte:
[1,2] + [3,4]
Respondeu com:
"1,23,4"
O que está acontecendo?
[5,6,7][1,2]
é 7
porque ele usa o último item na segunda matriz. Oo
Eu queria adicionar os elementos de uma matriz em outra, então tentei o seguinte:
[1,2] + [3,4]
Respondeu com:
"1,23,4"
O que está acontecendo?
[5,6,7][1,2]
é 7
porque ele usa o último item na segunda matriz. Oo
Respostas:
O +
operador não está definido para matrizes .
O que acontece é que o Javascript converte matrizes em seqüências de caracteres e concatena essas.
Como essa pergunta e, consequentemente, minha resposta está recebendo muita atenção, senti que seria útil e relevante ter uma visão geral sobre como o +
operador também se comporta em geral.
Então, aqui vai.
Excluindo E4X e outras coisas específicas de implementação, Javascript (a partir de ES5) tem 6 built-in tipos de dados :
Observe que, embora typeof
um pouco confuso retorne object
para Null e function
para objetos que podem ser chamados, Null na verdade não é um Object e, estritamente falando, nas implementações Javascript em conformidade com as especificações, todas as funções são consideradas objetos.
Isso mesmo - o Javascript não possui matrizes primitivas ; apenas instâncias de um objeto chamado Array
com um pouco de açúcar sintático para aliviar a dor.
Adicionando mais à confusão, as entidades do invólucro, como new Number(5)
, new Boolean(true)
e new String("abc")
são do object
tipo, não são números, booleanos ou seqüências de caracteres, como seria de esperar. No entanto, para operadores aritméticos Number
e Boolean
se comportam como números.
Calma, né? Com tudo isso fora do caminho, podemos avançar para a própria visão geral.
Diferentes tipos de resultado por tipos de +
operando
|| undefined | null | boolean | number | string | object |
=========================================================================
undefined || number | number | number | number | string | string |
null || number | number | number | number | string | string |
boolean || number | number | number | number | string | string |
number || number | number | number | number | string | string |
string || string | string | string | string | string | string |
object || string | string | string | string | string | string |
* aplica-se ao Chrome13, FF6, Opera11 e IE9. A verificação de outros navegadores e versões é deixada como um exercício para o leitor.
Nota: Como apontado por CMS , em determinados casos de objectos, tais como Number
, Boolean
e os personalizados do +
operador não necessariamente produzir um resultado string. Pode variar dependendo da implementação do objeto em conversão primitiva. Por exemplo, var o = { valueOf:function () { return 4; } };
avaliar o + 2;
produz 6
, a number
, avaliar o + '2'
produz '42'
, a string
.
Para ver como a tabela de visão geral foi gerada, visite http://jsfiddle.net/1obxuc7m/
O +
operador do JavaScript tem dois propósitos: adicionar dois números ou unir duas strings. Ele não possui um comportamento específico para matrizes, portanto, é convertê-las em strings e depois juntá-las.
Se você deseja unir duas matrizes para produzir uma nova, use o .concat
método :
[1, 2].concat([3, 4]) // [1, 2, 3, 4]
Se você deseja adicionar com eficiência todos os elementos de uma matriz para outra, é necessário usar o método .push :
var data = [1, 2];
// ES6+:
data.push(...[3, 4]);
// or legacy:
Array.prototype.push.apply(data, [3, 4]);
// data is now [1, 2, 3, 4]
O comportamento do +
operador é definido na Seção 11.6.1 do ECMA-262 5e :
11.6.1 O operador Adição (+)
O operador de adição executa concatenação de sequência ou adição numérica. A produção
AdditiveExpression : AdditiveExpression + MultiplicativeExpression
é avaliada da seguinte forma:
- Seja
lref
o resultado da avaliaçãoAdditiveExpression
.- Let
lval
beGetValue(lref)
.- Seja
rref
o resultado da avaliaçãoMultiplicativeExpression
.- Let
rval
beGetValue(rref)
.- Let
lprim
beToPrimitive(lval)
.- Let
rprim
beToPrimitive(rval)
.- Se
Type(lprim)
éString
ouType(rprim)
éString
, então
- Retorne a String resultante da concatenação
ToString(lprim)
seguida porToString(rprim)
- Retorne o resultado da aplicação da operação de adição a
ToNumber(lprim)
eToNumber(rprim)
. Veja a nota abaixo 11.6.3.
Você pode ver que cada operando é convertido ToPrimitive
. Lendo mais adiante, podemos descobrir que ToPrimitive
sempre converterá matrizes em strings, produzindo esse resultado.
Array.prototype.push.apply(data, [3, 4])
vez de data.concat([3,4])
?
concat
produz uma nova matriz, a chamada mais longa estende com eficiência uma matriz existente .
[].push.apply(data, [3,4])
para um pouco menos de verbosidade. Além disso, isso garante resistência a outras pessoas que alteram o valor de Array
.
Ele adiciona as duas matrizes como se fossem strings .
A representação de string para a primeira matriz seria "1,2" e a segunda seria "3,4" . Portanto, quando o +
sinal é encontrado, ele não pode somar matrizes e concatená-las como strings.
O +
concats strings, portanto, converte as matrizes em strings.
[1,2] + [3,4]
'1,2' + '3,4'
1,23,4
Para combinar matrizes, use concat
.
[1,2].concat([3,4])
[1,2,3,4]
Em JavaScript, o operador de adição binária ( +
) executa adição numérica e concatenação de cadeias. No entanto, quando o primeiro argumento não é um número nem uma string, ele é convertido em uma string (portanto, " 1,2
"), então ele faz o mesmo com o segundo " 3,4
" e os concatena em " 1,23,4
".
Tente usar o método "concat" de matrizes:
var a = [1, 2];
var b = [3, 4];
a.concat(b) ; // => [1, 2, 3, 4];
Parece que o JavaScript está transformando suas matrizes em strings e juntando-as. Se você deseja adicionar tuplas, precisará usar um loop ou uma função de mapa.
[1,2]+[3,4]
em JavaScript é o mesmo que avaliar:
new Array( [1,2] ).toString() + new Array( [3,4] ).toString();
e, para resolver seu problema, o melhor seria adicionar duas matrizes no local ou sem criar uma nova matriz:
var a=[1,2];
var b=[3,4];
a.push.apply(a, b);
Está fazendo exatamente o que você pediu.
O que você está adicionando são referências de matriz (que JS converte em strings), não números como parece. É como adicionar cordas: "hello " + "world"
="hello world"
seria bom se você pudesse sobrecarregar os operadores em JavaScript, mas não puder: Posso definir sobrecargas personalizadas do operador em Javascript? você pode hackear apenas o operador "==" que converte em cadeias antes de comparar: http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx
Isso ocorre porque, operador + assume que os operandos são string, se não forem números. Portanto, primeiro os converte em string e concats para fornecer o resultado final, se não for um número. Além disso, ele não suporta matrizes.
Algumas respostas aqui explicaram como a saída indesejada inesperada ( '1,23,4'
) acontece e algumas explicaram como obter o que elas assumem ser a saída desejada desejada ( [1,2,3,4]
), ou seja, concatenação de matriz. No entanto, a natureza do resultado esperado esperado é realmente um tanto ambígua, porque a pergunta original simplesmente declara "eu queria adicionar os elementos de uma matriz em outra ...". Isso pode significar concatenação de matriz, mas também adição de tupla (por exemplo, aqui e aqui ), ou seja, adicionar os valores escalares de elementos em uma matriz aos valores escalares dos elementos correspondentes na segunda, por exemplo, combinar [1,2]
e [3,4]
obter [4,6]
.
Supondo que ambas as matrizes tenham a mesma área / comprimento, aqui está uma solução simples:
const arr1 = [1, 2];
const arr2 = [3, 4];
const add = (a1, a2) => a1.map((e, i) => e + a2[i]);
console.log(add(arr1, arr2)); // ==> [4, 6]