61

I have an array I would like to split in half. So I can position the first half on the right side and the second half on the left side.

I have used the splice function before:

var leftSide = arrayName.splice(0,2);

But not sure how to splice it in half no matter the size, because the array will change in size dynamically.

scottt
  • 7,008
  • 27
  • 37
Xtian
  • 3,535
  • 11
  • 55
  • 91

10 Answers10

87
var half_length = Math.ceil(arrayName.length / 2);    

var leftSide = arrayName.slice(0,half_length);

edited the code following @Lightness Races in Orbit and @pubkey comments.

redmoon7777
  • 4,498
  • 1
  • 24
  • 26
  • 2
    `Math.ceil(arrayName.length / 2)` can replace seven and a third lines of your code, and avoid contaminating the global scope to boot. – Lightness Races in Orbit Feb 07 '12 at 17:54
  • 1
    This is dangerous because it mutates the original array 'arrayName'. You can prevent this by first calling slice(0) to copy the original array like arrayName.slice(0).splice(0, halfLength); – pubkey Mar 26 '22 at 22:06
75

Avoid Mutations

If you need to avoid mutations, for example if you have to split an array in react you don't want to mutate the original or it could lead to some very strange behaviour in your app.

What is a Mutation?

A mutation is when you change a non primitive, like an object or array. Using an array method like splice will cause the original array to be manipulated. You can always tell if a method will mutate by whether or not it returns a new array or object.

Why can Mutations be "bad"?

When you mutate an object or array you change that original reference. This means that if you use the original reference you will get the new value. This is best shown with an example.

// make a new object
const myObj = { key: "some value" };

// assign a new const to the object (this is assigned by reference)
const newObj = myObj;

// change the value of a key in the new const
newObj.key = "some other value";

// log the original object and see that its value has been changed
console.log(myObj) // will log { key: "some other value" };

As you can see the object myObj had the value of key changed as well. Scary stuff.

Use Slice

You can get around this by using slice instead of splice

Example

let yourArray = props.someArray;
let halfwayThrough = Math.floor(yourArray.length / 2)
// or instead of floor you can use ceil depending on what side gets the extra data

let arrayFirstHalf = yourArray.slice(0, halfwayThrough);
let arraySecondHalf = yourArray.slice(halfwayThrough, yourArray.length);
Joe Lloyd
  • 19,471
  • 7
  • 53
  • 81
23

You can simply refer to the array's length:

var leftSide = arrayName.splice(0, Math.floor(arrayName.length / 2));

Since .splice() actually removes elements from the source array, the remaining elements in the array will be the elements for the right half.

Math.floor() will round down to give the left side one less than the right side for odd lengths. You could use Math.ceil() if you want to round up to give the left side one more than the right side when the length is odd.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
6

You can use ES6 destructing also and slice() so that the original array isn't mutated.

   const yourArray;
   let leftSide,rightSide;
   const m = Math.floor(yourArray.length/2);
   const [leftSide,rightSide] = [yourArray.slice(0,m), yourArray.slice(m,yourArray.length)];
   console.log(leftSide);
   console.log(rightSide);
Pradeep Maurya
  • 71
  • 1
  • 2
  • 6
5
let leftSide = myArray.splice(0, Math.ceil(myArray.length / 2));
//The right side is stored in "myArray"

For example:

let letters = ['a', 'b', 'c', 'd', 'e'];
let leftSide = letters.splice(0, Math.ceil(letters.length /2));
let rightSide = letters;
console.log(leftSide);
=> ['a', 'b', 'c']
console.log(rightSide);
=> ['d', 'e']

More information: splice in the MDN docs


Note that this modifies your original array. If you want to keep the original array, clone the array, then use splice on the cloned array. From an SO question about cloning arrays:

There has been a huuuge BENCHMARKS thread, providing following information:

  • for blink browsers slice() is the fastest method, concat() is a bit slower, and while loop is 2.4x slower.

  • for other browsers while loop is the fastest method, since those browsers don't have internal optimizations for slice and concat.

//Fastest for Blink browsers (Opera/Chromium):
let clonedArray = originalArray.slice();
//For other browsers:
let clonedArray = [];
var i = myArray.length;
while (i--) clonedArray[i] = myArray[i];
Community
  • 1
  • 1
NonameSL
  • 1,405
  • 14
  • 27
5

Take a look at lodash chunk:

var myArray = [1, 2, 3, 4, 5, 6, 7, 8];
var pivot = _.ceil(myArray.length / 2);
// => 4
console.log(_.chunk(myArray, pivot));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
1

This is a fun function for Avoiding Mutations with options:

function splitArray({ alternate, array }) {
  const halfIndex = Math.ceil(array.length / 2) - 1;
  let firstArray = true;
  return array.reduce((res, item, index) => {
    if (firstArray) {
      res[0].push(item);
      if (alternate || index >= halfIndex) {
        firstArray = false;
      }
    } else {
      res[1].push(item);
      if (alternate) {
        firstArray = true;
      }
    }
    return res;
  }, [[], []]);
}

And you can call it with an alternating option:

const myArray = [1,2,3,4,5,6,7,8];
const splitAlternate = splitArray({ alternate: true, array: myArray });
const splitNoAlternate = splitArray({ alternate: false, array: myArray });

console.log(myArray);
console.log(splitAlternate);
console.log(splitNoAlternate);
parker
  • 3,929
  • 1
  • 16
  • 19
0

Another alternative, you probably shouldn't use it though.

[1,2,3,4,5,6,7,8,9,10].reduce(([l, r], cur, i, self) => i < self.length / 2 ? [[...l, cur], r] : [l, [...r, cur]], [[], []])
Teiem
  • 1,329
  • 15
  • 32
0

if you want the size of the array to stay equal you just need to alternate which array you write to (eg, alternate .push calls on the arrays).. Why don't you just create 2 arrays up front?

var lelftHalf = yourArray.splice(0,arrayName.length / 2);

After you do that if you want to keep the 2 arrays the same size alternate between

leftHalf.push(newElement);

and

yourArray.push(newElement1);
Matt Wolfe
  • 8,924
  • 8
  • 60
  • 77
-1

you can use filter as another available way to solve it.

let arr = [1,2,3,4,5,6];
let half = arr.filter((el, i) => i >= arr.length/2);
aleha_84
  • 8,309
  • 2
  • 38
  • 46