TwilioQuest Javascript Lab Constant Vigilance - javascript

OBJECTIVE:
This function should take a single argument - an array of strings. Your scan function must loop through all the strings in this array, and examine each one using boolean logic.
If a string in the input array is equal to the value contraband, add the index of that item to an output array. When you have finished scanning the entire input array, return the output array, which should contain all the indexes of suspicious items in the array.
For example, given an input array of:
['contraband', 'apples', 'cats', 'contraband', 'contraband']
Your function should return the array:
[0, 3, 4]
This list contains the position inside the input array of all the contraband strings.
MY CODE:
function scan(freightItems) {
let contrabandIndexes = [];
freightItems.forEach(el => {
console.log(freightItems.indexOf(el, 0));
if (el == "contraband") {
contrabandIndexes.push(freightItems.indexOf(el, 0));
}
});
return contrabandIndexes;
}
const indexes = scan(['dog', 'contraband', 'cat', 'zippers', 'contraband']);
console.log('Contraband Indexes: ' + indexes); // should be [1, 4]
I cant figure out why the index of the second 'contraband' is coming back as 1 and why I'm not getting past this level in TwilioQuest. Any help is appreciated.

Try something like this:
function scan(freightItems) {
let contrabandIndexes = [];
freightItems.forEach((el, idx) => {
if (el == 'contraband') {
contrabandIndexes.push(idx);
}
});
return contrabandIndexes;
}
const indexes = scan(['dog', 'contraband', 'cat', 'zippers', 'contraband']);
console.log('Contraband Indexes: ' + indexes); // should be [1, 4]
indexOf is for searching an array:
The indexOf() method returns the first index at which a given element
can be found in the array
but el is an item in the array.

Related

Why are the array elements not being modified inside the `filter` method?

I’m trying to understand the filter method. I found a script example and modified it to multiply all elements of the original array by two:
function zeroFill() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
console.log(list)
const multiplyByTwo = (ar) => ar.filter((word, index, arr) => {
arr[index + 1] *= 2
return true
})
console.log(multiplyByTwo(list))
}
All but the first element of the array get modified. If I change the arr[index + 1] to arr[index], none of the elements get modified. I am trying to understand how this works.
As you already know map is the correct way to achieve the mentioned requirement let me try to explain why the filter is not working.
You must understand the return value of the filter which is a new array with the elements that pass the test.
function zeroFill() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0];
console.log("before = ", list);
const multiplyByTwo = (ar) =>
ar.filter((word, index, arr) => {
arr[index] *= 2; // <--- Manipulating the current list
return true; // <----- Return the current element: word
});
console.log("after = ", multiplyByTwo(list));
}
zeroFill();
In the case of arr[index] * 2, you are multiplying each element by 2 (and modifying the list array too) but you are returning the current element that is represented by word in the above code.
filter returns a new array with the array elements of list based on its return value.
The array values do get modified in both cases, i.e. when using arr[index + 1] *= 2 and arr[index] *= 2.
However, the value that lands in the resulting array is the same value passed as word.
See the specification:
The array element at index k of array O is retrieved and stored as kValue.
The callback function is called with arguments (kValue, k, O).
If the callback function returns a truthy value, put kValue into the resulting array.
At no point is the array element at index k of array O retrieved again.
Your modification with arr[index] *= 2 always comes too late; the value that is going to be added has already been retrieved from the array by the filter method.
Your modifications with arr[index + 1] *= 2 will modify the next index, which is the value that filter retrieves in the next iteration.
That’s why you see changed values starting from index 1.
Index 0 didn’t see a modification yet, so filter receives the original value and adds it to the resulting array.
Log list, not only multiplyByTwo(list), to see the changed values.
You are misusing filter here.
You should use map instead to change every value to a different value, or forEach if you want to mutate the array with something like arr[index + 1] *= 2.
To multiply every element by two:
console.log(list.map((value) => value * 2));
The filter function is not designed for this purpose. It's designed to filter out the array elements you need.
For your specific case, I would use .map method, as it will modify the array as needed and is designed to walk arrays.
const multiplyByTwo = (ar) => ar.map((current) => current * 2);
You are trying to modify an array with .filter which is not a good practice. You can use .map when you want to do something with the array items.
function zeroFill() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
console.log(list)
const multiplyByTwo = ( ar) => ar.map( (item, index, ) => {
return item *= 2
})
console.log(multiplyByTwo(list))
}
zeroFill();
First I will try to explain why you got this behavior, run this code and try to understand:
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
function zeroFill() {
console.log('list before filter: ', list)
const multiplyByTwo = ( ar) => ar.filter((word, index, arr) => {
console.log(arr === list); //arr and list have the same reference
arr[index] *= 2; //you will be modifing list[index], that is the current value being filtered, so you you will get the old value
//arr[index + 1] *= 2; //you will modifying list[index + 1], so in the next loop the value will be the new one
return true
}); //The result of filter will create a new array
console.log('multiplyByTwo result:', multiplyByTwo(list))
console.log('list after filter: ', list);
}
You should use .filter just to pick the values you want based on a condition, not to modify an array while you are filtering it, you should use .map for this purpose:
const list = [1, 0, 1, 2, 3, 0, 0, 4, 0];
const multiplyByTwo = list.map((current) => current * 2);
Array.filter(), as the name states, filters the array and returns a new array containing the items that pass the filter.
What you need is Array.map() if you want a mapped (and also new) array. Otherwise you can use Array.forEach()
// In this function, a new array is created and returned, with modified items
function zeroFillWithMap() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
const multiplyByTwo = list.map(i => i*2)
console.log('Mapped New Array', multiplyByTwo)
}
zeroFillWithMap();
// In this function, a new array is NOT created and the items of the original array are modified
function zeroFillWithForEach() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
list.forEach((item, index, originalArray) => originalArray[index] *= 2)
console.log('Modified Original Array', list)
}
zeroFillWithForEach();
I am not sure if you know about the "Map Method In JS". I think the problem you proposed could be solved much easily using that method. I am gonna leave my code here on how i solved your problem.
const zeroFill = (list) => {
console.log("orignal array: " + list);
const multiplyByTwo = list.map((item) => {
return item * 2;
});
console.log("multiplied by two array: " + multiplyByTwo);
};
zeroFill([1, 0, 1, 2, 3, 0, 0, 4, 0]);
but if you need your problem solved using only the filter method, I'd be happy to help in that situation too.
And yeah, if you want to know more about "Map Method In Javascript". I am gonna link few articles from MDN and W3SCHOOL.
https://www.w3schools.com/jsref/jsref_map.asp
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

console.log vs return: different results (JS)

I don't understand why the code below gives different results in console.log inside the filter function and in the return function:
function expandedForm(num) {
let arr = num.toString().split('').reverse().filter(function(el, ind){
console.log("iter:"+ el * Math.pow(10,ind));
return (el*Math.pow(10,ind))
});
console.log(arr);
return arr;
}
expandedForm(402);
gives this:
iter:2
iter:0
iter:400
[ '2', '4' ]
=> [ '2', '4' ]
EDIT:
Apparently, I haven't been clear enough. To be straightforward, why I get 400 in console.log and 4 in filter? So the question regards more the evaluation of the expression el * Math.pow(10,ind)
Because filter on array does not manipulate the elements in array
For eg:
const arr = [1, 2, 3];
const newArr = arr.filter(e => {
const newElement = e * 100;
return newElement;
}
Here we expect newArray to be [100, 200, 300] but we receive it [1, 2, 3].
Reason - return value from filter is just for true/false concern, it does not actually return the value. This is the reason why you are not getting value for 0.
You can try below code if you want an output [2, 0, 400]
const arr = num.toString().split('').reverse().map((el, ind) => {
return (el * Math.pow(10,ind));
});
If you want an output as [2, 400],
const arr = num.toString().split('').reverse().map((el, ind) => {
return (el * Math.pow(10,ind));
}).filter(e => e);
num.split('') return one array ['2', '0', '4'],
num.split('').filter(function(){ return handler()}) return the elements when hander() is true, then the second selmement is '0', its final result is 0, so it will not keep this element.
Finnally, the reuslt is ['2', '4']
As Array.prototype.filter() defined: (Look into the description on the parameter=callback).
Syntax
var newArray = arr.filter(callback[, thisArg])
Parameters
callback
Function is a predicate, to test each element of the array. Return true to keep the element, false otherwise, taking three arguments:
element
The current element being processed in the array.
indexOptional
The index of the current element being processed in the array.
arrayOptional
The array filter was called upon.
thisArg Optional
Optional. Value to use as this when executing callback.
You need to read the documentation of .filter function https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
A new array with the elements that pass the test. If no elements pass
the test, an empty array will be returned.
It doesn't matter what you return inside from filter function all it cares about if its true of false for each index. As you have 0 in 402 it skips the middle element and returns only elements which are >0

Removing elements from array after pulling data from firebase

I am pulling an object from firebase converting it to an array then doing remove element operation on it but there is some strange behaviour:
this.players = this.db.object('arena/players').valueChanges();
this.players.subscribe(players =>{
console.log(players);
this.playersarray= Object.keys(players).map(key => ({ key, value: players[key] }));
console.log(this.playersarray);
console.log(this.playersarray.length);
for(var i =0;i<this.playersarray.length;i++){
if(this.playersarray[i].value != "waiting"){
console.log(this.playersarray[i].value+"deleting");
this.playersarray.splice(i,1);
}
}
console.log(this.playersarray);
});
This is console:
I am trying to remove elements which value are not equal to waiting.So in this case im expecting to remove engincan,lifesuxtr and get last console.log as only someotheruser,someuser
but lifesuxtr is not removed ??? only engincan removed ?
You can use Array.filter operator to iterate over the Array and filter our the relevant results, example:
const arr = [1, 2, 3, 4, 5];
const result = arr.filter((item) => item % 2 === 1);
console.log(result);
When you remove the items from the array, the index of all following items shift down. Because you're removing an item, your loop skips an item.
// Array starts as:
// 0 1 2 3
// ['a', 'b', 'c', 'd']
// Loop 1: Index 0, item 'a'. Matches test, remove it.
// Array becomes:
// 0 1 2
// ['b', 'c', 'd']
// Loop 2: Index 1, item 'c'.
// Loop 3: Index 2, item 'd'.
The quickest fix is to change the index by subtracting one from it but that's can get hard to keep track of quickly. I'd recommend using the Array.filter() method.
this.playersarray = this.playersarray.filter(function(player) {
return player.value != 'waiting'
})
Simple way to remove array element by value.
var playersarray = {
"name": "John",
"age": 30,
"cars": "Ford"
};
for(value in playersarray){
if(playersarray[value] != "Ford"){
delete playersarray[value]; //deleting array elements if no 'Ford'
}
}
console.log(playersarray);
Output: {cars:"Ford"}

Remove elements from array except particular one

I have two arrays. First one is an array of indexes and second one is an array of objects. They look like this:
var nums = [0, 2];
var obj = [Object_1, Object_2, Object_3];
In this particular case I need to remove all "obj" elements except obj[0] and obj[2]. So the result will look like this:
obj = [Object_2]
There are also may be cases when nums = [0, 1, 2] and obj = [Object_1, Object_2, Object_3]; In that case I dont need to remove any elements.
The "obj" length is always greater than "nums" length.
So I started with finding only the elements that I need to save:
nums.forEach(function(key) {
obj.forEach(function(o, o_key) {
if (key === o_key) {
console.log(key, o);
// deleting remaining elements
}
});
});
The question: How can I remove elements that dont meets my condition? I dont need the new array, I want to modify the existing "obj" array. How can I achieve this functionality? Or should I use some another techniques?
You coudld check if the length of the indices is the same length of the object array and return or delete the objects at the given indices.
It needs a sorted array for indices, because Array#splice changes the length of the array. (With an array with descending sorted indices, you could use Array#forEach instead of Array#reduceRight.)
function mutate(objects, indices) {
if (objects.length === indices.length) {
return;
}
indices.reduceRight(function (_, i) {
objects.splice(i, 1);
}, null);
}
var objects = [{ o: 1 }, { o: 2 }, { o: 3 }];
mutate(objects, [0, 1, 2]); // keep all items
console.log(objects);
objects = [{ o: 1 }, { o: 2 }, { o: 3 }]; // delete items at index 0 and 2
mutate(objects, [0, 2]);
console.log(objects);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do this with a filter, assuming nums is an array on indexes of elements you want to keep.
obj = obj.filter((o, i) => nums.indexOf(i) > -1);
If you want to keep the same array object, you need to use splice e.g. in a simple reverse for in order to not mess the indices:
for (var i=obj.length-1; i>=0; i--) {
if (nums.indexOf(i) < 0) {
obj.splice(i, 1);
}
}
This is assuming the list of indices (nums) is ordered. If not, we first need to sort it:
var sortedNums = nums.sort(function (a, b) { return a - b; });
And then use the sortedNums to check the indexOf

How to insert an item into an array at a specific index (JavaScript)

I am looking for a JavaScript array insert method, in the style of:
arr.insert(index, item)
Preferably in jQuery, but any JavaScript implementation will do at this point.
You want the splice function on the native array object.
arr.splice(index, 0, item); will insert item into arr at the specified index (deleting 0 items first, that is, it's just an insert).
In this example we will create an array and add an element to it into index 2:
var arr = [];
arr[0] = "Jani";
arr[1] = "Hege";
arr[2] = "Stale";
arr[3] = "Kai Jim";
arr[4] = "Borge";
console.log(arr.join()); // Jani,Hege,Stale,Kai Jim,Borge
arr.splice(2, 0, "Lene");
console.log(arr.join()); // Jani,Hege,Lene,Stale,Kai Jim,Borge
You can implement the Array.insert method by doing this:
Array.prototype.insert = function ( index, ...items ) {
this.splice( index, 0, ...items );
};
Then you can use it like:
var arr = [ 'A', 'B', 'E' ];
arr.insert(2, 'C', 'D');
// => arr == [ 'A', 'B', 'C', 'D', 'E' ]
Other than splice, you can use this approach which will not mutate the original array, but it will create a new array with the added item. It is useful, when you need to avoid mutation. I'm using the ES6 spread operator here.
const items = [1, 2, 3, 4, 5]
const insert = (arr, index, newItem) => [
// part of the array before the specified index
...arr.slice(0, index),
// inserted item
newItem,
// part of the array after the specified index
...arr.slice(index)
]
const result = insert(items, 1, 10)
console.log(result)
// [1, 10, 2, 3, 4, 5]
This can be used to add more than one item by tweaking the function a bit to use the rest operator for the new items, and spread that in the returned result as well:
const items = [1, 2, 3, 4, 5]
const insert = (arr, index, ...newItems) => [
// part of the array before the specified index
...arr.slice(0, index),
// inserted items
...newItems,
// part of the array after the specified index
...arr.slice(index)
]
const result = insert(items, 1, 10, 20)
console.log(result)
// [1, 10, 20, 2, 3, 4, 5]
Custom array insert methods
1. With multiple arguments and chaining support
/* Syntax:
array.insert(index, value1, value2, ..., valueN) */
Array.prototype.insert = function(index) {
this.splice.apply(this, [index, 0].concat(
Array.prototype.slice.call(arguments, 1)));
return this;
};
It can insert multiple elements (as native splice does) and supports chaining:
["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(1, 6);
// ["b", "X", "Y", "Z", "c"]
2. With array-type arguments merging and chaining support
/* Syntax:
array.insert(index, value1, value2, ..., valueN) */
Array.prototype.insert = function(index) {
index = Math.min(index, this.length);
arguments.length > 1
&& this.splice.apply(this, [index, 0].concat([].pop.call(arguments)))
&& this.insert.apply(this, arguments);
return this;
};
It can merge arrays from the arguments with the given array and also supports chaining:
["a", "b", "c", "d"].insert(2, "V", ["W", "X", "Y"], "Z").join("-");
// "a-b-V-W-X-Y-Z-c-d"
DEMO: http://jsfiddle.net/UPphH/
Using Array.prototype.splice() is an easy way to achieve it
const numbers = ['one', 'two', 'four', 'five']
numbers.splice(2, 0, 'three');
console.log(numbers)
Read more about Array.prototype.splice
If you want to insert multiple elements into an array at once check out this Stack Overflow answer: A better way to splice an array into an array in javascript
Also here are some functions to illustrate both examples:
function insertAt(array, index) {
var arrayToInsert = Array.prototype.splice.apply(arguments, [2]);
return insertArrayAt(array, index, arrayToInsert);
}
function insertArrayAt(array, index, arrayToInsert) {
Array.prototype.splice.apply(array, [index, 0].concat(arrayToInsert));
return array;
}
Finally here is a jsFiddle so you can see it for yourself: http://jsfiddle.net/luisperezphd/Wc8aS/
And this is how you use the functions:
// if you want to insert specific values whether constants or variables:
insertAt(arr, 1, "x", "y", "z");
// OR if you have an array:
var arrToInsert = ["x", "y", "z"];
insertArrayAt(arr, 1, arrToInsert);
Solutions & Performance
Today (2020.04.24) I perform tests for chosen solutions for big and small arrays. I tested them on macOS v10.13.6 (High Sierra) on Chrome 81.0, Safari 13.1, and Firefox 75.0.
Conclusions
For all browsers
surprisingly for small arrays, non-in-place solutions based on slice and reduce (D,E,F) are usually 10x-100x faster than in-place solutions
for big arrays the in-place-solutions based on splice (AI, BI, and CI) was fastest (sometimes ~100x - but it depends on the array size)
for small arrays the BI solution was slowest
for big arrays the E solution was slowest
Details
Tests were divided into two groups: in-place solutions (AI, BI, and CI) and non-in-place solutions (D, E, and F) and was performed for two cases:
test for an array with 10 elements - you can run it here
test for an array with 1,000,000 elements - you can run it here
Tested code is presented in the below snippet:
jsfiddle
function AI(arr, i, el) {
arr.splice(i, 0, el);
return arr;
}
function BI(arr, i, el) {
Array.prototype.splice.apply(arr, [i, 0, el]);
return arr;
}
function CI(arr, i, el) {
Array.prototype.splice.call(arr, i, 0, el);
return arr;
}
function D(arr, i, el) {
return arr.slice(0, i).concat(el, arr.slice(i));
}
function E(arr, i, el) {
return [...arr.slice(0, i), el, ...arr.slice(i)]
}
function F(arr, i, el) {
return arr.reduce((s, a, j)=> (j-i ? s.push(a) : s.push(el, a), s), []);
}
// -------------
// TEST
// -------------
let arr = ["a", "b", "c", "d", "e", "f"];
let log = (n, f) => {
let a = f([...arr], 3, "NEW");
console.log(`${n}: [${a}]`);
};
log('AI', AI);
log('BI', BI);
log('CI', CI);
log('D', D);
log('E', E);
log('F', F);
This snippet only presents tested code (it not perform tests)
Example results for a small array on Google Chrome are below:
For proper functional programming and chaining purposes, an invention of Array.prototype.insert() is essential. Actually, the splice could have been perfect if it had returned the mutated array instead of a totally meaningless empty array. So here it goes:
Array.prototype.insert = function(i,...rest){
this.splice(i,0,...rest)
return this
}
var a = [3,4,8,9];
document.write("<pre>" + JSON.stringify(a.insert(2,5,6,7)) + "</pre>");
Well, OK, the above with the Array.prototype.splice() one mutates the original array and some might complain like "you shouldn't modify what doesn't belong to you" and that might turn out to be right as well. So for the public welfare, I would like to give another Array.prototype.insert() which doesn't mutate the original array. Here it goes;
Array.prototype.insert = function(i,...rest){
return this.slice(0,i).concat(rest,this.slice(i));
}
var a = [3,4,8,9],
b = a.insert(2,5,6,7);
console.log(JSON.stringify(a));
console.log(JSON.stringify(b));
You can use splice() for this
The splice() method usually receives three arguments when adding an element:
The index of the array where the item is going to be added.
The number of items to be removed, which in this case is 0.
The element to add.
let array = ['item 1', 'item 2', 'item 3']
let insertAtIndex = 0
let itemsToRemove = 0
array.splice(insertAtIndex, itemsToRemove, 'insert this string on index 0')
console.log(array)
I recommend using pure JavaScript in this case. Also there isn't any insert method in JavaScript, but we have a method which is a built-in Array method which does the job for you. It's called splice...
Let's see what's splice()...
The splice() method changes the contents of an array by removing
existing elements and/or adding new elements.
OK, imagine we have this array below:
const arr = [1, 2, 3, 4, 5];
We can remove 3 like this:
arr.splice(arr.indexOf(3), 1);
It will return 3, but if we check the arr now, we have:
[1, 2, 4, 5]
So far, so good, but how we can add a new element to array using splice?
Let's put back 3 in the arr...
arr.splice(2, 0, 3);
Let's see what we have done...
We use splice again, but this time for the second argument, we pass 0, meaning we don't want to delete any item, but at the same time, we add a third argument which is the 3 that will be added at second index...
You should be aware that we can delete and add at the same time. For example, now we can do:
arr.splice(2, 2, 3);
Which will delete two items at index 2. Then add 3 at index 2 and the result will be:
[1, 2, 3, 5];
This is showing how each item in splice work:
array.splice(start, deleteCount, item1, item2, item3 ...)
Here are two ways:
const array = [ 'My', 'name', 'Hamza' ];
array.splice(2, 0, 'is');
console.log("Method 1: ", array.join(" "));
Or
Array.prototype.insert = function ( index, item ) {
this.splice( index, 0, item );
};
const array = [ 'My', 'name', 'Hamza' ];
array.insert(2, 'is');
console.log("Method 2 : ", array.join(" "));
Append a single element at a specific index
// Append at a specific position (here at index 1)
arrName.splice(1, 0,'newName1');
// 1: index number, 0: number of element to remove, newName1: new element
// Append at a specific position (here at index 3)
arrName[3] = 'newName1';
Append multiple elements at a specific index
// Append from index number 1
arrName.splice(1, 0, 'newElemenet1', 'newElemenet2', 'newElemenet3');
// 1: index number from where append start,
// 0: number of element to remove,
//newElemenet1,2,3: new elements
Array#splice() is the way to go, unless you really want to avoid mutating the array. Given 2 arrays arr1 and arr2, here's how you would insert the contents of arr2 into arr1 after the first element:
const arr1 = ['a', 'd', 'e'];
const arr2 = ['b', 'c'];
arr1.splice(1, 0, ...arr2); // arr1 now contains ['a', 'b', 'c', 'd', 'e']
console.log(arr1)
If you are concerned about mutating the array (for example, if using Immutable.js), you can instead use slice(), not to be confused with splice() with a 'p'.
const arr3 = [...arr1.slice(0, 1), ...arr2, ...arr1.slice(1)];
Another possible solution, with usage of Array.reduce.
const arr = ["apple", "orange", "raspberry"];
const arr2 = [1, 2, 4];
const insert = (arr, item, index) =>
arr.reduce(function(s, a, i) {
i === index ? s.push(item, a) : s.push(a);
return s;
}, []);
console.log(insert(arr, "banana", 1));
console.log(insert(arr2, 3, 2))
Even though this has been answered already, I'm adding this note for an alternative approach.
I wanted to place a known number of items into an array, into specific positions, as they come off of an "associative array" (i.e. an object) which by definition is not guaranteed to be in a sorted order. I wanted the resulting array to be an array of objects, but the objects to be in a specific order in the array since an array guarantees their order. So I did this.
First the source object, a JSONB string retrieved from PostgreSQL. I wanted to have it sorted by the "order" property in each child object.
var jsonb_str = '{"one": {"abbr": "", "order": 3}, "two": {"abbr": "", "order": 4}, "three": {"abbr": "", "order": 5}, "initialize": {"abbr": "init", "order": 1}, "start": {"abbr": "", "order": 2}}';
var jsonb_obj = JSON.parse(jsonb_str);
Since the number of nodes in the object is known, I first create an array with the specified length:
var obj_length = Object.keys(jsonb_obj).length;
var sorted_array = new Array(obj_length);
And then iterate the object, placing the newly created temporary objects into the desired locations in the array without really any "sorting" taking place.
for (var key of Object.keys(jsonb_obj)) {
var tobj = {};
tobj[key] = jsonb_obj[key].abbr;
var position = jsonb_obj[key].order - 1;
sorted_array[position] = tobj;
}
console.dir(sorted_array);
Immutable insertion
Using the splice method is surely the best answer if you need to insert into an array in-place.
However, if you are looking for an immutable function that returns a new updated array instead of mutating the original array on insert, you can use the following function.
function insert(array, index) {
const items = Array.prototype.slice.call(arguments, 2);
return [].concat(array.slice(0, index), items, array.slice(index));
}
const list = ['one', 'two', 'three'];
const list1 = insert(list, 0, 'zero'); // Insert single item
const list2 = insert(list, 3, 'four', 'five', 'six'); // Insert multiple
console.log('Original list: ', list);
console.log('Inserted list1: ', list1);
console.log('Inserted list2: ', list2);
Note: This is a pre-ES6 way of doing it, so it works for both older and newer browsers.
If you're using ES6 then you can try out rest parameters too; see this answer.
Anyone who's still having issues with this one and have tried all the options in previous answers and never got it. I'm sharing my solution, and this is to take into consideration that you don't want to explicitly state the properties of your object vs the array.
function isIdentical(left, right){
return JSON.stringify(left) === JSON.stringify(right);
}
function contains(array, obj){
let count = 0;
array.map((cur) => {
if(this.isIdentical(cur, obj))
count++;
});
return count > 0;
}
This is a combination of iterating the reference array and comparing it to the object you wanted to check, converting both of them into a string, and then iterating if it matched. Then you can just count. This can be improved, but this is where I settled.
Taking profit of the reduce method as follows:
function insert(arr, val, index) {
return index >= arr.length
? arr.concat(val)
: arr.reduce((prev, x, i) => prev.concat(i === index ? [val, x] : x), []);
}
So in this way we can return a new array (will be a cool functional way - more much better than using push or splice) with the element inserted at index, and if the index is greater than the length of the array it will be inserted at the end.
I tried this and it is working fine!
var initialArr = ["India","China","Japan","USA"];
initialArr.splice(index, 0, item);
Index is the position where you want to insert or delete the element.
0, i.e., the second parameter, defines the number of elements from the index to be removed.
item contains the new entries which you want to make in the array. It can be one or more than one.
initialArr.splice(2, 0, "Nigeria");
initialArr.splice(2, 0, "Australia","UK");
I have to agree with Redu's answer because splice() definitely has a bit of a confusing interface. And the response given by cdbajorin that "it only returns an empty array when the second parameter is 0. If it's greater than 0, it returns the items removed from the array" is, while accurate, proving the point.
The function's intent is to splice or as said earlier by Jakob Keller, "to join or connect, also to change.
You have an established array that you are now changing which would involve adding or removing elements...." Given that, the return value of the elements, if any, that were removed is awkward at best. And I 100% agree that this method could have been better suited to chaining if it had returned what seems natural, a new array with the spliced elements added. Then you could do things like ["19", "17"].splice(1,0,"18").join("...") or whatever you like with the returned array.
The fact that it returns what was removed is just kind of nonsense IMHO. If the intention of the method was to "cut out a set of elements" and that was its only intent, maybe. It seems like if I don't know what I'm cutting out already though, I probably have little reason to cut those elements out, doesn't it?
It would be better if it behaved like concat(), map(), reduce(), slice(), etc. where a new array is made from the existing array rather than mutating the existing array. Those are all chainable, and that is a significant issue. It's rather common to chain array manipulation.
It seems like the language needs to go one or the other direction and try to stick to it as much as possible. JavaScript being functional and less declarative, it just seems like a strange deviation from the norm.
I like a little safety and I use this:
Array.prototype.Insert = function (item, before) {
if (!item) return;
if (before == null || before < 0 || before > this.length - 1) {
this.push(item);
return;
}
this.splice(before, 0, item);
}
var t = ["a", "b"]
t.Insert("v", 1)
console.log(t)
You can do it with array.splice:
/**
* #param arr: Array
* #param item: item to insert
* #param index: index at which to insert
* #returns array with the inserted element
*/
export function _arrayInsertAt<T>(arr: T[], item: T, index: number) {
return arr.splice(index, 0, item);;
}
Doc of array.slice
Here's a working function that I use in one of my applications.
This checks if an item exists:
let ifExist = (item, strings = [ '' ], position = 0) => {
// Output into an array with an empty string. Important just in case their isn't any item.
let output = [ '' ];
// Check to see if the item that will be positioned exist.
if (item) {
// Output should be equal to an array of strings.
output = strings;
// Use splice() in order to break the array.
// Use positional parameters to state where to put the item
// and 0 is to not replace an index. Item is the actual item we are placing at the prescribed position.
output.splice(position, 0, item);
}
// Empty string is so we do not concatenate with comma or anything else.
return output.join("");
};
And then I call it below.
ifExist("friends", [ ' ( ', ' )' ], 1)} // Output: ( friends )
ifExist("friends", [ ' - '], 1)} // Output: - friends
ifExist("friends", [ ':'], 0)} // Output: friends:
Here is the modern (Typescript functional) way:
export const insertItemInList = <T>(
arr: T[],
index: number,
newItem: T
): T[] => [...arr.slice(0, index), newItem, ...arr.slice(index)]
I do it like so:
const insert = (what, where, index) =>
([...where.slice(0, index), what , ...where.slice(index, where.length)]);
const insert = (what, where, index) =>
([...where.slice(0, index), what , ...where.slice(index, where.length)]);
const list = [1, 2, 3, 4, 5, 6];
const newList = insert('a', list, 2);
console.log(newList.indexOf('a') === 2);
Here's a simple function that supports inserting multiple values at the same time:
function add_items_to_array_at_position(array, index, new_items)
{
return [...array.slice(0, index), ...new_items, ...array.slice(index)];
}
Usage example:
let old_array = [1,2,5];
let new_array = add_items_to_array_at_position(old_array, 2, [3,4]);
console.log(new_array);
//Output: [1,2,3,4,5]
var array= [10,20,30,40]
var i;
var pos=2; //pos=index + 1
/*pos is position which we want to insert at which is index + 1.position two in an array is index 1.*/
var value=5
//value to insert
//Initialize from last array element
for(i=array.length-1;i>=pos-1;i--){
array[i+1]=array[i]
}
array[pos-1]=value
console.log(array)
Multi purpose for ARRAY and ARRAY OF OBJECT reusable approach
let arr = [0,1,2];
let obj = [{ name: "abc"},{ name: "xyz"},{ name: "ijk"} ];
const addArrayItemAtIndex = ( array, index, newItem ) => {
return [...array.slice(0, index), newItem, ...array.slice(index)];
}
// For Array
console.log( addArrayItemAtIndex(arr, 2, 159 ) );
// For Array of Objects
console.log( addArrayItemAtIndex(obj, 0, { name: "AMOOS"} ) );

Categories