Splice an array in half, no matter the size?
JavascriptArraysJavascript Problem Overview
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.
Javascript Solutions
Solution 1 - Javascript
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.
Solution 2 - Javascript
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.
const myObj = { key: "some value" };
const newObj = myObj;
newObj.key = "some other value";
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);
Solution 3 - Javascript
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.
Solution 4 - Javascript
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>
Solution 5 - Javascript
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);
Solution 6 - Javascript
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];
Solution 7 - Javascript
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);
Solution 8 - Javascript
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);
Solution 9 - Javascript
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]], [[], []])
Solution 10 - Javascript
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);