195

I'm trying to combine 2 arrays in JavaScript into one.

var lines = new Array("a","b","c");
lines = new Array("d","e","f");

This is a quick example, I want to be able to combine them so that when the second line is read the 4th element in the array would return "d"

How would I do this?

4
  • 3
    Same question, more (detailed) answers: stackoverflow.com/questions/1584370 Commented Aug 18, 2012 at 6:44
  • 3
    @David All simple questions have more answers, because more people google them (or ::shivers:: use the site's built-in search feature). Commented Dec 14, 2012 at 6:58
  • 13
    @ignis This is not a duplicate. That question is specifically asking about removing duplicates in the resulting array. It is more specific, and this question is much more general. Commented Aug 22, 2015 at 16:08
  • These days, it is important to distinguish, whether you really do need an array, or if an iterable will suffice, because the answer would be different. Commented Sep 25, 2024 at 13:11

3 Answers 3

311
var a = ['a','b','c'];
var b = ['d','e','f'];
var c = a.concat(b); //c is now an an array with: ['a','b','c','d','e','f']
console.log( c[3] ); //c[3] will be 'd'
Sign up to request clarification or add additional context in comments.

10 Comments

@Matt yes because its just an array it doesn't track its contents.
@geotheory check underscorejs there is a reduce fonction for that underscorejs.org ;)
old post, but for anyone googling now, @geotheory's question has a simple answer: Array.prototype.concat.apply([], [[1,2],[3,4],[5,6]])
with es6 : c=a.push(...b)
You can also do: const newArr = [...arr1, ...arr2];
|
26

Using ES6 JavaScript - spread syntax:

const a = ['a', 'b', 'c'];
const b = ['d', 'e', 'f'];

const c = [...a, ...b]; // c = ['a', 'b', 'c', 'd', 'e', 'f']

It is also the fastest way to concatenate arrays in JavaScript today.


However, when dealing with large arrays, it is more efficient to chain them (concatenate logically):

function chainArrays<T>(...arr: T[][]): Iterable<T> {
    return {
        [Symbol.iterator](): Iterator<T> {
            let i = 0, k = -1, a: T[] = [];
            return {
                next(): IteratorResult<T> {
                    while (i === a.length) {
                        if (++k === arr.length) {
                            return {done: true, value: undefined};
                        }
                        a = arr[k];
                        i = 0;
                    }
                    return {value: a[i++], done: false};
                }
            };
        }
    }
}

// usage example:

const a = [1, 2];
const b = [3, 4];
const c = [5, 6];

for (const value of chainArrays(a, b, c)) {
    console.log(value); //=> 1, 2, 3, 4, 5, 6
}

Above, we have to use while(i === a.length) logic in order to skip all empty arrays, while also for jumping to the next array at the end of the current one.

A generator approach for the same is much simpler, while also slower:

function* chainArrays<T>(...arr: T[][]) {
    for (const i of arr)
        for (const v of i)
            yield v;
}

// test:

for (const value of chainArrays(a, b, c)) {
    console.log(value); //=> 1, 2, 3, 4, 5, 6
}

Internally, a generator is translated into a more verbose IterableIterator, which used to perform slower than a manual iterable, but JavaScript engines keep improving, so it's for you to test it out in your environment ;) But I tested it under Node v20, and on average the manual iterable performs 2 times faster than our generator here.

For a complete TypeScript implementation (including reversed logic), see this gist, or this repo.

2 Comments

Helpful (+1) but got a source or at least an argument for the "fastest way" claim?
@kjhughes You can find it here and many online benchmarks. Basically, spread is much faster for small arrays, while concat is faster for large arrays, while also memory-inefficient (it copies much data), that's why I extended my answer into linking/chaining arrays, for better efficiency.
4

Speed test using local nodejs v16.4.
Object Spread is 3x faster.

ObjectCombining.js

export const ObjectCombining1 = (existingArray, arrayToAdd) => {
  const newArray = existingArray.concat(arrayToAdd);
  return newArray;
};

export const ObjectCombining2 = (existingArray, arrayToAdd) => {
  const newArray = [ ...existingArray, ...arrayToAdd ]
  return newArray
};

ObjectCombining.SpeedTest.js

import Benchmark from 'benchmark';

import * as methods from './ObjectCombining.js';

let suite = new Benchmark.Suite();

const existingArray = ['a', 'b', 'c'];
const arrayToAdd = ['d', 'e', 'f'];

Object.entries(methods).forEach(([name, method]) => {
  suite = suite.add(name, () => method(existingArray, arrayToAdd));

  console.log(name, '\n', method(existingArray, arrayToAdd),'\n');
});

suite
  .on('cycle', (event) => {
    console.log(`🏎  ${event.target}`);
  })
  .on('complete', function () {
    console.log(`\n🏁 ${this.filter('fastest').map('name')} is fastest.\n`);
  })
  .run({ async: false });

Result results

2 Comments

Can you add existingArray.push(...arrayToAdd) test, please?
@vitaly-t or, given that the benchmark is rather useless - don't.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.