JS join arrays with replacement - javascript

There are 2 arrays:
var arr1 = ["a", "b", "c"];
var arr2 = ["k", ,"l","m","n"];
Need some standart function that returns:
var arr3=["k","b","l"];
This one is too slow:
function join_arrays(arr1,arr2)
{
var arr3=[];
for(var i=0;i<arr1.length;i++)
if(arr2[i]==undefined)
arr3[i]=arr1[i];
else
arr3[i]=arr2[i];
return arr3;
}

You could do the following:
var arr1 = ["a", "b", "c"];
var arr2 = ["k",undefined,"l","m","n"];
var arr3 = [];
function join_arrays(arr1,arr2){
arr3 = arr2;
var i = arr3.indexOf(undefined);
while(i !=- 1){
arr3[i] = arr1[i];
i = arr3.indexOf(undefined);
}
return arr3;
}
However there is a little caveat here, as far as my testing in JSBin showed me, which is that you have to have set the empty values that are gonna be replaced to undefined explicitly as I did in my example. If this is not optimal for you, there might be a better way than what I showed here.
Hopefully this runs faster than your code, as it will only go through the loop as many times as needed to do the replacements and will fill arr3 with arr2 right away.
UPDATE:
Bear in mind that, while the above function works, it is unsafe because when the second array has empty elements in an index that is not present in the first one, it will cause an error. Therefore you could do something like this:
function join_arrays(arr1,arr2){
arr3=arr2;
var i = arr3.indexOf(undefined);
while(i!=-1 && i<arr1.length){
arr3[i]=arr1[i];
i=arr3.indexOf(undefined);
}
return arr3;
}
So for var arr2 = ["k",undefined,undefined,"l","m","n",undefined] result will be ["k", "b", "c", "l", "m", "n", undefined] with this method, instead of getting an error or infinite loop!

With use standard functions, it's can be faster.
let arr1 = ["a", "b", "c"];
let arr2 = ["k", ,"l","m","n"];
arr1.map((e,i)=>arr2[i]==undefined?e:arr2[i])

Probably this single liner should do your job.
var arr3 = arr1.forEach((e,i) => arr2[i] === void 0 ? arr3.push(e): arr3.push(arr2[i]));

Related

How do I filter array of objects based on a list of possible ID properties?

I'm trying to filter arr2. If the element doesn't have an ID listed in arr, then I want it to be removed. How could I make this happen in javascript?
var arr= ["a", "b", "d"]
var arr2=[{id:"a", value:1},{id:"b", value:2}, {id:"c", value:3}]
result:
[{id:"a", value:1},{id:"b", value:2}]
Thanks in advance :)
You can use reduce and in the callback function check if arr includes the id of the object under iteration. If so then add the elements in the accumulator array
var arr = ["a", "b", "d"]
var arr2 = [{
id: "a",
value: 1
}, {
id: "b",
value: 2
}, {
id: "c",
value: 3
}];
const newData = arr2.reduce((acc, curr) => {
if (arr.includes(curr.id)) {
acc.push(curr)
}
return acc;
}, []);
console.log(newData)
if arr items are always strings you can do this:
var arr = ["a", "b", "d"];
var arr2 = [{id:"a", value:1},{id:"b", value:2}, {id:"c", value:3}];
let str = arr.join('')
let filtered = arr2.filter(x => str.includes(x.id));
console.log(filtered)
this should do it
var arr= ["a", "b", "d"]
var arr2=[{id:"a", value:1},{id:"b", value:2}, {id:"c", value:3}]
const filteredArray = arr2.filter(obj => {
return arr.includes(obj.id)
})
Using filter, reduce, and includes are all nearly twice as slow as simply using a loop. To walk you through it, all it does is check over every element in the second array and check to see if it's id property is in the first array, and if it is, it clones it. Also, for future reference, that title is written poorly. A much better title would be "How to filter array of objects based on a list of possible ID properties"
var arr= ["a", "b", "d"]
var arr2=[{id:"a", value:1},{id:"b", value:2}, {id:"c", value:3}]
let clone = []
for(let i = 0;i < arr2.length;i++){
for(let j = 0;j < arr.length; j++) if(arr2[i].id === arr[j]) clone.push(arr2[j])
}
console.log(clone)

how to convert multidimention array to arr in object

can you explain the logic how to convert this 2d array to array and in array has objects, here is the input :
const arr = [
["Tony", "a", "b"],
["Sara", "c", "z"]
];
how to convert them to be:
obj = [
{
name:"Tony",
first:"a",
second:"b"
},
{
name:"Sara",
first:"c",
second:"z"
}
]
should we create 2 objects temporary and are ? to put them in the array,
and how about looping? can we just use one-time looping?
and how if that 2d array length is not same with ther 2d on the first or the second,
i do love to know the method, with explaning if you dont mind,
and i do like you all dont use ES6 for this :), so i know the logic
Use Array.map(). In the map's callback, extract the values to variables, using array destructuring, than create the object with shorthand property names:
const arr = [["Tony", "a", "b"], ["Sara", "c", "z"]];
const result = arr.map(([name, first, second]) => ({
name,
first,
second
}));
console.log(result);
And if you don't want to use Array.map(), you can build one using a for...of loop:
const map = (arr, cb) => {
const r = [];
for(const item of arr) {
r.push(cb(item));
}
return r;
};
const arr = [["Tony", "a", "b"], ["Sara", "c", "z"]];
const result = map(arr, ([name, first, second]) => ({
name,
first,
second
}));
console.log(result);
You can use .map() with some array destructuring:
const arr = [
["Tony", "a", "b"],
["Sara", "c", "z"]
];
const result = arr.map(([name, first, second]) => ({name, first, second}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Alternatively, you can use a simple for loop:
const arr = [
["Tony", "a", "b"],
["Sara", "c", "z"]
];
const result = [];
for(var i = 0; i < arr.length; i++) {
result.push({
name: arr[i][0],
first: arr[i][1],
second: arr[i][2]
});
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var arr = [["Tony", "a", "b"], ["Sara", "c", "z"]];
function parseData(input){
var output = [];
for(var i = 0; i< input.length ; i++){
output.push({name:input[i][0],first:input[i][1],second:input[i][2]})
}
return output;
}
console.log(parseData(arr));
EDIT - Explanation
As the input is structured as 2D array with inner array is of fixed length of 3 and outer is of non-negative ( >= 0 ). Iterate over the outer array using for loop and inner array using the index number and store the result in output array.
JsFiddle demo - https://jsfiddle.net/53umf8rv/
Without Map:
const arr = [
["Tony", "a", "b"],
["Sara", "c", "z"]
];
obj=[];
for(innerArr of arr)
{
obj.push({"name":innerArr[0],"first":innerArr[1],"second":innerArr[2]});
}
console.log(obj);
Without using higher order functions you can achieve this using a for of loop:
const arr = [
["Tony", "a", "b"],
["Sara", "c", "z"]
];
let obj_arr = [];
for(inner_arr of arr) {
obj_arr = [...obj_arr, {name: inner_arr[0], first: inner_arr[1], second: inner_arr[2]}];
}
console.log(obj_arr);
You could use an outer for ... of statement, which iterates the items of the array and iterate the inner array by using a classic for statement with an index variable, which is used to get the corresponding key value as well.
For each inner iteration take a new property for the temporary object and assign a value. At the end of the inner iteration push the temporary object to the result set.
function convert(array, keys) {
var result = [],
items,
i,
temp;
for (items of array) {
temp = {};
for (i = 0; i < items.length; i++) {
temp[keys[i]] = items[i];
}
result.push(temp);
}
return result;
}
console.log(convert([["Tony", "a", "b"], ["Sara", "c", "z"]], ["name", "first", "second"]));

How to rearrange an array by indices array?

Given an array arr and an array of indices ind, I'd like to rearrange arr in-place to satisfy the given indices. For example:
var arr = ["A", "B", "C", "D", "E", "F"];
var ind = [4, 0, 5, 2, 1, 3];
rearrange(arr, ind);
console.log(arr); // => ["B", "E", "D", "F", "A", "C"]
Here is a possible solution that uses O(n) time and O(1) space, but mutates ind:
function swap(arr, i, k) {
var temp = arr[i];
arr[i] = arr[k];
arr[k] = temp;
}
function rearrange(arr, ind) {
for (var i = 0, len = arr.length; i < len; i++) {
if (ind[i] !== i) {
swap(arr, i, ind[i]);
swap(ind, i, ind[i]);
}
}
}
What would be the optimal solution if we are limited to O(1) space and mutating ind is not allowed?
Edit: The algorithm above is wrong. See this question.
This is the "sign bit" solution.
Given that this is a JavaScript question and the numerical literals specified in the ind array are therefore stored as signed floats, there is a sign bit available in the space used by the input.
This algorithm cycles through the elements according to the ind array and shifts the elements into place until it arrives back to the first element of that cycle. It then finds the next cycle and repeats the same mechanism.
The ind array is modified during execution, but will be restored to its original at the completion of the algorithm. In one of the comments you mentioned that this is acceptable.
The ind array consists of signed floats, even though they are all non-negative (integers). The sign-bit is used as an indicator for whether the value was already processed or not. In general, this could be considered extra storage (n bits, i.e. O(n)), but as the storage is already taken by the input, it is not additional acquired space. The sign bits of the ind values which represent the left-most member of a cycle are not altered.
Edit: I replaced the use of the ~ operator, as it does not produce the desired results for numbers equal or greater than 231, while JavaScript should support numbers to be used as array indices up to at least 232 - 1. So instead I now use k = -k-1, which is the same, but works for the whole range of floats that is safe for use as integers. Note that as alternative one could use a bit of the float's fractional part (+/- 0.5).
Here is the code:
var arr = ["A", "B", "C", "D", "E", "F"];
var ind = [4, 0, 5, 2, 1, 3];
rearrange(arr, ind);
console.log('arr: ' + arr);
console.log('ind: ' + ind);
function rearrange(arr, ind) {
var i, j, buf, temp;
for (j = 0; j < ind.length; j++) {
if (ind[j] >= 0) { // Found a cycle to resolve
i = ind[j];
buf = arr[j];
while (i !== j) { // Not yet back at start of cycle
// Swap buffer with element content
temp = buf;
buf = arr[i];
arr[i] = temp;
// Invert bits, making it negative, to mark as visited
ind[i] = -ind[i]-1;
// Visit next element in cycle
i = -ind[i]-1;
}
// dump buffer into final (=first) element of cycle
arr[j] = buf;
} else {
ind[j] = -ind[j]-1; // restore
}
}
}
Although the algorithm has a nested loop, it still runs in O(n) time: the swap happens only once per element, and also the outer loop visits every element only once.
The variable declarations show that the memory usage is constant, but with the remark that the sign bits of the ind array elements -- in space already allocated by the input -- are used as well.
Index array defines a permutation. Each permutation consists of cycles. We could rearrange given array by following each cycle and replacing the array elements along the way.
The only problem here is to follow each cycle exactly once. One possible way to do this is to process the array elements in order and for each of them inspect the cycle going through this element. If such cycle touches at least one element with lesser index, elements along this cycle are already permuted. Otherwise we follow this cycle and reorder the elements.
function rearrange(values, indexes) {
main_loop:
for (var start = 0, len = indexes.length; start < len; start++) {
var next = indexes[start];
for (; next != start; next = indexes[next])
if (next < start) continue main_loop;
next = start;
var tmp = values[start];
do {
next = indexes[next];
tmp = [values[next], values[next] = tmp][0]; // swap
} while (next != start);
}
return values;
}
This algorithm overwrites each element of given array exactly once, does not mutate the index array (even temporarily). Its worst-case complexity is O(n2). But for random permutations its expected complexity is O(n log n) (as noted in comments for related answer).
This algorithm could be optimized a little bit. Most obvious optimization is to use a short bitset to keep information about several indexes ahead of current position (whether they are already processed or not). Using a single 32-or-64-bit word to implement this bitset should not violate O(1) space requirement. Such optimization would give small but noticeable speed improvement. Though it does not change worst case and expected asymptotic complexities.
To optimize more, we could temporarily use the index array. If elements of this array have at least one spare bit, we could use it to maintain a bitset allowing us to keep track of all processed elements, which results in a simple linear-time algorithm. But I don't think this could be considered as O(1) space algorithm. So I would assume that index array has no spare bits.
Still the index array could give us some space (much larger then a single word) for look-ahead bitset. Because this array defines a permutation, it contains much less information than arbitrary array of the same size. Stirling approximation for ln(n!) gives n ln n bits of information while the array could store n log n bits. Difference between natural and binary logarithms gives us to about 30% of potential free space. Also we could extract up to 1/64 = 1.5% or 1/32 = 3% free space if size of the array is not exactly a power-of-two, or in other words, if high-order bit is only partially used. (And these 1.5% could be much more valuable than guaranteed 30%).
The idea is to compress all indexes to the left of current position (because they are never used by the algorithm), use part of free space between compressed data and current position to store a look-ahead bitset (to boost performance of the main algorithm), use other part of free space to boost performance of the compression algorithm itself (otherwise we'll need quadratic time for compression only), and finally uncompress all the indexes back to original form.
To compress the indexes we could use factorial number system: scan the array of indexes to find how many of them are less than current index, put the result to compressed stream, and use available free space to process several values at once.
The downside of this method is that most of free space is produced when algorithm comes to the array's end while this space is mostly needed when we are at the beginning. As a result, worst-case complexity is likely to be only slightly less than O(n2). This could also increase expected complexity if not this simple trick: use original algorithm (without compression) while it is cheap enough, then switch to the "compressed" variant.
If length of the array is not a power of 2 (and we have partially unused high-order bit) we could just ignore the fact that index array contains a permutation, and pack all indexes as if in base-n numeric system. This allows to greatly reduce worst-case asymptotic complexity as well as speed up the algorithm in "average case".
This proposal utilizes the answer of Evgeny Kluev.
I made an extension for faster processing, if all elements are already treated, but the index has not reached zero. This is done with an additional variable count, which counts down for every replaced element. This is used for leaving the main loop if all elements are at right position (count = 0).
This is helpful for rings, like in the first example with
["A", "B", "C", "D", "E", "F"]
[ 4, 0, 5, 2, 1, 3 ]
index 5: 3 -> 2 -> 5 -> 3
index 4: 1 -> 0 -> 4 -> 1
Both rings are at first two loops rearranged and while each ring has 3 elements, the count is now zero. This leads to a short circuit for the outer while loop.
function rearrange(values, indices) {
var count = indices.length, index = count, next;
main: while (count && index--) {
next = index;
do {
next = indices[next];
if (next > index) continue main;
} while (next !== index)
do {
next = indices[next];
count--;
values[index] = [values[next], values[next] = values[index]][0];
} while (next !== index)
}
}
function go(values, indices) {
rearrange(values, indices);
console.log(values);
}
go(["A", "B", "C", "D", "E", "F"], [4, 0, 5, 2, 1, 3]);
go(["A", "B", "C", "D", "E", "F"], [1, 2, 0, 4, 5, 3]);
go(["A", "B", "C", "D", "E", "F"], [5, 0, 1, 2, 3, 4]);
go(["A", "B", "C", "D", "E", "F"], [0, 1, 3, 2, 4, 5]);
This answer has been updated to satisfy OP's conditions
In this answer there are no temp arrays and ind array doesn't get re-ordered or sorted by any means. All replacing operations are done in a single pass. getItemIndex function receives only a shallow portion of the ind array to work with. It's just done by harnessing all the information hidden in the ind array.
It's key to understand that the ind array keeps all history for us.
We have the following information by examining the ind array.
By looking at the items we find the index map of the corresponding item at arr array.
Each items index tells us how many swaps done before. We get history.
Each items index also tells if there was a previous swap related with the current index position where did the previous element go. We can do like ind.indexOf(i); Anyways here is the code;
I have added a few functions like Array.prototype.swap() to make the code interpreted easier. Here is the code.
Array.prototype.swap = function(i,j){
[this[i],this[j]] = [this[j],this[i]];
return this;
};
function getItemIndex(a,i){
var f = a.indexOf(i);
return f !=-1 ? getItemIndex(a,f) : i;
}
function sort(arr,ind){
ind.forEach((n,i,x) => x.indexOf(i) > i ? arr.swap(i,x[i]) // item has not changed before so we can swap
: arr.swap(getItemIndex(ind.slice(0,i),i),x[i])); // item has gone to somwhere in previous swaps get it's index and swap
return arr;
}
var arr = ["A", "B", "C", "D", "E", "F"],
ind = [4, 0, 5, 2, 1, 3];
console.log(sort(arr,ind),ind);
Ok the very final version of this code is this. It is very simplified and includes a test case with 26 letters. Each time you run you will get a different purely random unique indexes map.
Array.prototype.swap = function(i,j){
i !=j && ([this[i],this[j]] = [this[j],this[i]]);
return this;
};
Array.prototype.shuffle = function(){
var i = this.length,
j;
while (i > 1) {
j = ~~(Math.random()*i--);
[this[i],this[j]] = [this[j],this[i]];
}
return this;
};
var arr = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"],
ind = (new Array(arr.length)).fill("").map((e,i) => e = i).shuffle();
console.log(JSON.stringify(arr));
console.log(JSON.stringify(ind));
function getItemIndex(a,i,j){
var f = a.indexOf(i);
return f < j ? getItemIndex(a,f,j) : i;
}
function sort(arr,ind){
ind.forEach((n,i,x) => arr.swap(getItemIndex(ind,i,i),n));
return arr;
}
console.log(JSON.stringify(sort(arr,ind)));
console.log(JSON.stringify(ind));
So ok as per the comment from Trincot here it goes with an iterative getItemIndex() function.
Array.prototype.swap = function(i,j){
i !=j && ([this[i],this[j]] = [this[j],this[i]]);
return this;
};
Array.prototype.shuffle = function(){
var i = this.length,
j;
while (i > 1) {
j = ~~(Math.random()*i--);
[this[i],this[j]] = [this[j],this[i]];
}
return this;
};
var arr = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"],
ind = (new Array(arr.length)).fill("").map((e,i) => e = i).shuffle();
console.log(JSON.stringify(arr));
console.log(JSON.stringify(ind));
function getItemIndex(a,i){
var f = a.indexOf(i),
j;
if (f >= i) return i; // this element hasn't been moved before.
while (f < i) { // this element has been swapped so get this elements current index
j = f;
f = a.indexOf(f);
}
return j;
}
function sort(arr,ind){
ind.forEach((n,i,x) => arr.swap(getItemIndex(ind,i),n));
return arr;
}
console.log(JSON.stringify(sort(arr,ind)));
console.log(JSON.stringify(ind));
var arr = ["A", "B", "C", "D", "E", "F"];
var ind = [4, 0, 5, 2, 1, 3];
function rearrange(arr, ind){
var map = [];
for (var i = 0; i < arr.length; i++) map[ind[i]] = arr[i];
for (var i = 0; i < arr.length; i++) arr[i] = map[i];
}
rearrange(arr, ind);
console.log(arr);
That works but, because I'm not a smart developper, I assume it's probably not the fastest algorithm.
Below, one may find a PARTIAL solution for a case when we have only ONE cycle, i.e.
var arr = ["A", "B", "C", "D", "E", "F"];
var ind = [4, 2, 5, 0, 1, 3];
function rearrange( i, arr, ind, temp ){
if( temp ){
if( arr[ind[i]] ){
var temp2 = arr[ind[i]];
arr[ind[i]] = temp;
rearrange( ind[i], arr, ind, temp2 );
}
else{ // cycle
arr[ind[i]] = temp;
// var unvisited_index = ...;
// if( unvisited_index ) rearrange( unvisited_index, arr, ind, "" );
}
}
else{
if( i == ind[i] ){
if( i < arr.length ) rearrange( i + 1, arr, ind, temp );
}
else{
temp = arr[ind[i]];
arr[ind[i]]=arr[i];
arr[i] = "";
i = ind[i];
rearrange(i, arr, ind, temp );
}
}
}
rearrange( 0, arr, ind, "" );
To make this solution to work for a general case, we need to find total numbers of unique cycles and one index from each of them.
For the OP example:
var arr = ["A", "B", "C", "D", "E", "F"];
var ind = [4, 0, 5, 2, 1, 3];
There are 2 unique cycles:
4 -> 1 -> 0 -> 4
5 -> 3 -> 2 -> 5
If one runs
rearrange( 0, arr, ind, "" );
rearrange( 5, arr, ind, "" );
S(he) will get desirable output for the OP problem.
I'm not sure on the time, but the map function does appear to do what was requested. It's an option, but since I don't know the inner workings of .map then I can't say for sure this is what you're looking for.
var arr = ["A", "B", "C", "D", "E", "F"];
var ind = [4, 0, 5, 2, 1, 3];
arr = ind.map(function(value)
{ return arr[value]; });
Another solution that doesn't use the map function could look something like this:
var arr = ["A", "B", "C", "D", "E", "F"];
var ind = [4, 0, 5, 2, 1, 3];
var temp = [];
for (var i = 0, ind_length = ind.length; i < ind_length; i++)
{
var set_index = ind[i];
temp.push(arr[set_index]);
delete arr[set_index];
}
arr = temp;
This makes good use of space by using the delete option which also keeps the indexes from shifting. Since it's only doing one loop I imagine the execution is rather fast. Since the commands are very basic and simple this should be a viable solution. It's not quite what was asked which was a swap with no extra space used, but it comes pretty close. I'm new to answering questions like this one so please... constructive criticism.
Try this:
var result = new Array(5);
for (int i = 0; i < result.length; i++) {
result[i] = arr[ind[i]];
}
console.log(arr);
I am using ind as indexes in it's own order
var arr = ["A", "B", "C", "D", "E", "F"];
var ind = [4, 0, 5, 2, 1, 3];
var obj = {}
for(var i=0;i<arr.length;i++)
obj[ind[i]]=arr[i];
console.log(obj);
Working Fiddle

Removing Element From Array of Arrays with Regex

I'm using regex to test certain elements in an array of arrays. If an inner array doesn't follow the desired format, I'd like to remove it from the main/outer array. The regex I'm using is working correctly. I am not sure why it isn't removing - can anyone advise or offer any edits to resolve this problem?
for (var i = arr.length-1; i>0; i--) {
var a = /^\w+$/;
var b = /^\w+$/;
var c = /^\w+$/;
var first = a.test(arr[i][0]);
var second = b.test(arr[i][1]);
var third = c.test(arr[i][2]);
if ((!first) || (!second) || (!third)){
arr.splice(i,1);
}
When you cast splice method on an array, its length is updated immediately. Thus, in future iterations, you will probably jump over some of its members.
For example:
var arr = ['a','b','c','d','e','f','g']
for(var i = 0; i < arr.length; i++) {
console.log(i, arr)
if(i%2 === 0) {
arr.splice(i, 1) // remove elements with even index
}
}
console.log(arr)
It will output:
0 ["a", "b", "c", "d", "e", "f", "g"]
1 ["b", "c", "d", "e", "f", "g"]
2 ["b", "c", "d", "e", "f", "g"]
3 ["b", "c", "e", "f", "g"]
4 ["b", "c", "e", "f", "g"]
["b", "c", "e", "f"]
My suggestion is, do not modify the array itself if you still have to iterate through it. Use another variable to save it.
var arr = ['a','b','c','d','e','f','g']
var another = []
for(var i = 0; i < arr.length; i++) {
if(i%2) {
another.push(arr[i]) // store elements with odd index
}
}
console.log(another) // ["b", "d", "f"]
Or you could go with Array.prototype.filter, which is much simpler:
arr.filter(function(el, i) {
return i%2 // store elements with odd index
})
It also outputs:
["b", "d", "f"]
Your code seems to work to me. The code in your post was missing a } to close the for statement but that should have caused the script to fail to parse and not even run at all.
I do agree with Leo that it would probably be cleaner to rewrite it using Array.prototype.filter though.
The code in your question would look something like this as a filter:
arr = arr.filter(function (row) {
return /^\w+$/.test(row[0]) && /^\w+$/.test(row[1]) && /^\w+$/.test(row[2]);
});
jsFiddle
I'm assuming it is 3 different regular expressions in your actual code, if they are all identical in your code you can save a little overhead by defining the RegExp literal once:
arr = arr.filter(function (row) {
var rxIsWord = /^\w+$/;
return rxIsWord.test(row[0]) && rxIsWord.test(row[1]) && rxIsWord.test(row[2]);
});

split an array into two based on a index in javascript

I have an array with a list of objects. I want to split this array at one particular index, say 4 (this in real is a variable). I want to store the second part of the split array into another array. Might be simple, but I am unable to think of a nice way to do this.
Use slice, as such:
var ar = [1,2,3,4,5,6];
var p1 = ar.slice(0,4);
var p2 = ar.slice(4);
You can use Array#splice to chop all elements after a specified index off the end of the array and return them:
x = ["a", "b", "c", "d", "e", "f", "g"];
y = x.splice(3);
console.log(x); // ["a", "b", "c"]
console.log(y); // ["d", "e", "f", "g"]
use slice:
var bigOne = [0,1,2,3,4,5,6];
var splittedOne = bigOne.slice(3 /*your Index*/);
I would recommend to use slice() like below
ar.slice(startIndex,length);
or
ar.slice(startIndex);
var ar = ["a","b","c","d","e","f","g"];
var p1 = ar.slice(0,3);
var p2 = ar.slice(3);
console.log(p1);
console.log(p2);
const splitAt = (i, arr) => {
const clonedArray = [...arr];
return [clonedArray.splice(0, i), clonedArray];
}
const [left, right] = splitAt(1, [1,2,3,4])
console.log(left) // [1]
console.log(right) // [2,3,4]
const [left1, right1] = splitAt(-1, [1,2,3,4])
console.log(left1) // []
console.log(right1) // [1,2,3,4]
const [left2, right2] = splitAt(5, [1,2,3,4])
console.log(left1) // [1,2,3,4]
console.log(right1) // []
Some benefits compared to other solutions:
You can get the result with a one liner
When split index is underflow or overflow, the result is still correct. slice will not behave correctly.
It does not mutate the original array. Some splice based solutions did.
There is only 1 splice operation, rather than 2 slice operations. But you need to benchmark to see if there is actual performance difference.
You can also use underscore/lodash wrapper:
var ar = [1,2,3,4,5,6];
var p1 = _.first(ar, 4);
var p2 = _.rest(ar, 4);
Simple one function from lodash:
const mainArr = [1,2,3,4,5,6,7]
const [arr1, arr2] = _.chunk(mainArr, _.round(mainArr.length / 2));
const splitArrayByIndex = (arr, index) => {
if (index > 0 && index < arr.length) {
return [arr.slice(0, index), arr.slice(-1 * (arr.length - index))]
}
}
const input = ['a', 'x', 'c', 'r']
const output = splitArrayByIndex(input, 2)
console.log({ input, output })

Categories

Resources