Javascript: Insert item into an the exact center of an array - javascript

Apologies if this is an asked/answered thing, but I did a general search and couldn't find the result I was looking for.
Say I've got an array, but I don't know the length of it, for whatever reason. I want to insert items into the array at an exact position (in this case, the center)
For the purposes of this question, I'll provide the array and how I got the output to read properly..
function insertIntoMiddle(array, item) {
array.splice(4, 2, item);
return array.sort();
}
const items = insertIntoMiddle([1, 3], 2);
console.log(insertIntoMiddle([1, 3], 2), '<-- should be [1 , 2 , 3]');
console.log(insertIntoMiddle([1, 3, 7, 9], 5), '<-- should be [1, 3, 5, 7, 9]');
And we get an output of:
[1, 2, 3] <-- should be [1 , 2 , 3]
[1, 3, 5, 7, 9] <-- should be [1, 3, 5, 7, 9]
Which is as it should be.. But my question is, what if, for whatever reason, say it's a database that's being read into an array for manipulation, and over time the database has grown. We don't know how long the array is..But we still want to insert into the EXACT middle of the array.. How would one go about doing that?

You could splice it with the half of the length.
function insertIntoMiddle(array, item) {
array.splice(array.length >> 1, 0, item);
return array
}
console.log(...insertIntoMiddle([1, 3], 2));
console.log(...insertIntoMiddle([1, 3, 7, 9], 5));

You can use two pointers, move first with +2 and second with +1, untill the end.
when the first one is at the end second one will be at the middle.
Insert the item at the position of second pointer.
function insertIntoMiddle(array, item) {
let i = 0;
let j = 0;
while (array[i]) {
i += 2;
j++;
}
array.splice(j, 0, item);
return array;
}
console.log(insertIntoMiddle([1, 3, 7, 9], 5));
console.log(insertIntoMiddle([1, 3], 2));

Related

javascript Delete from array between 2 indices

With an array of: [1, 2, 3, 4, 5, 6]
I would like to delete between 2 indices such as 2 and 4 to produce [1, 2, null, null, 5, 6]. What's the easiest way to do this?
Hopefully better than this:
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
let i = 2;
const rangeEnd = 9;
while (i < rangeEnd) {
delete array[i];
i++;
}
console.log(array)
If you want to use some native API you can actually do this with splice(). Otherwise, you should iterate a for loop through your array and change the value in each iteration.
Here is an example of how it would be done:
const array = [1, 2, 3, 4, 5, 6]
array.splice(3, 2, null, null) // the First element is beginning index and the second is count one will indicate how many indexes you need to traverse from the first one, then you should provide replace element for each of them.
console.log(array)
Note: For more info about it you can read more here.
There is a possible workaround for large scale replacement, so I will give it a touch here:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var anotherArr = Array(2).fill(null); // or you can simply define [null, null, ...]
Array.prototype.splice.apply(arr, [3, anotherArr.length].concat(anotherArr));
console.log(arr);
As you mean the range (2, 4] so you can follow this:
The range is: lower limit exclusive and the upper limit inclusive.
const arr = [1, 2, 3, 4, 5, 6];
const deleteRange = (arr, f, t) => {
return arr.map((item, i) => {
if (i + 1 > f && i + 1 <= t) {
return null;
}
return item;
})
}
console.log(deleteRange(arr, 2, 4));

How to modify value of n dimensional array element where indices are specified by an array in Javascript

I have an n-dimensional array and I want to access/modify an element in it using another array to specify the indices.
I figured out how to access a value, however I do not know how to modify the original value.
// Arbitrary values and shape
arr = [[[8, 5, 8],
[9, 9, 9],
[0, 0, 1]],
[[7, 8, 2],
[9, 8, 3],
[9, 5, 6]]];
// Arbitrary values and length
index = [1, 2, 0];
// The following finds the value of arr[1][2][0]
// Where [1][2][0] is specified by the array "index"
tmp=arr.concat();
for(i = 0; i < index.length - 1; i++){
tmp = tmp[index[i]];
}
// The correct result of 9 is returned
result = tmp[index[index.length - 1]];
How can I modify a value in the array?
Is there a better/more efficient way to access a value?
This is a classic recursive algorithm, as each step includes the same algorithm:
Pop the first index from indices.
Keep going with the array that the newly-popped index points to.
Until you get to the last element in indices - then replace the relevant element in the lowest-level array.
function getUpdatedArray(inputArray, indices, valueToReplace) {
const ans = [...inputArray];
const nextIndices = [...indices];
const currIndex = nextIndices.shift();
let newValue = valueToReplace;
if (nextIndices.length > 0) {
newValue = getUpdatedArray(
inputArray[currIndex],
nextIndices,
valueToReplace,
);
} else if (Array.isArray(inputArray[currIndex])) {
throw new Error('Indices array points an array');
}
ans.splice(currIndex, 1, newValue);
return ans;
}
const arr = [
[
[8, 5, 8],
[9, 9, 9],
[0, 0, 1]
],
[
[7, 8, 2],
[9, 8, 3],
[9, 5, 6]
]
];
const indices = [1, 2, 0];
const newArr = getUpdatedArray(arr, indices, 100)
console.log(newArr);
You can change the values in array like this,
arr[x][y][z] = value;
Does this help?
I think what you're looking for is this:
arr[index[0]][index[1]][index[2]] = value;
I'm having trouble understanding what you're attempting to do in the second part of your example.

I do not understand this solution

I start by pointing out that this code works. That is not the problem! I just don't understand how really. As I understand it the chunked.push method ads a new array all the time. But obviously, it does not. It gives the right answer:
[[ 1, 2], [3, 4], [5]]
I simply do not understand what is happening in this code. It spits out the right answer and put several items in each array if necessary but the code creates a new subarray each time, no? No, obviously not - but I don't understand why not? Please help!
function chunk(array, size) {
let workArr = [...array];
let chunked = [];
for (let i = 0; i < workArr.length; i++) {
let last = chunked[chunked.length - 1];
if (!last || last.length === size) {
chunked.push([workArr[i]])
} else {
last.push(workArr[i]);
}
}
return chunked;
}
Here is examples of some input parameters and expected results:
// chunk([1, 2, 3, 4], 2) --> [[ 1, 2], [3, 4]]
// chunk([1, 2, 3, 4, 5], 2) --> [[ 1, 2], [3, 4], [5]]
// chunk([1, 2, 3, 4, 5, 6, 7, 8], 3) --> [[ 1, 2, 3], [4, 5, 6], [7, 8]]
// chunk([1, 2, 3, 4, 5], 4) --> [[ 1, 2, 3, 4], [5]]
// chunk([1, 2, 3, 4, 5], 10) --> [[ 1, 2, 3, 4, 5]]
Let's break it
This copies an array there is used a spread operator
let workArr = [...array];
Iterate over every item in workArr array
for (let i = 0; i < workArr.length; i++) {
}
I think this would give you undefined at first run, because there is nothing at index -1 in chunked (because at first, chunked.length is 0), but it will set last to last element of chunked array
let last = chunked[chunked.length - 1];
If last has falsey value (0, null, undefined, "", NaN, false) or length of last equals to size (be aware, that last should be array or string), then push i-th element (indexing from 0) of workArr array into chunked array as an array, else push that element from workArr into last, but last then should be an array
if (!last || last.length === size) {
chunked.push([workArr[i]])
} else {
last.push(workArr[i]);
}
then simply return chunked array
return chunked;

javascript, forEach and removeChild unpredictable behavior

I wish to remove all items from a list and replace them with others
var list = document.querySelector("ul");
[].forEach.call(list.childNodes, list.removeChild.bind(list));
The code above does not work as expected, instead it removes only half the items (leaving every second item in the list).
If i change it to
var list = document.querySelector("ul");
[].slice.call(list.childNodes).forEach(list.removeChild.bind(list));
Then it works as expected,
can anyone explain ?
In the first one you are mutating an array you are iterating over.
In the second you are making a copy and then iterating over it.
The following is another option that doesn't require making a copy:
for(; list.firstChild; list.removeChild(list.firstChild));
This removes the firstChild while it is not null.
Concept
To explain the "unpredictable" behavior in the first scenario, consider this case:
var array = [0, 1, 2, 3, 4, 5, 6, 7];
This makes the behavior easier to explain without the distracting .call() and .bind() methods to wrap your head around.
array.forEach(function(num, index) {
console.log(num, index);
array.splice(index, 1);
});
You may be wondering why the output is:
0 0
2 1
4 2
6 3
But it's actually really simple. .forEach() iterates over the indices until i < array.length is no longer satisfied, while at the beginning of each iteration, your array looks like this:
[0, 1, 2, 3, 4, 5, 6, 7];
^
0
[1, 2, 3, 4, 5, 6, 7];
^
1
[1, 3, 4, 5, 6, 7];
^
2
[1, 3, 5, 6, 7];
^
3
[1, 3, 5, 7];
^
(4 < array.length) !== true
This is what happens when you manipulate an array being iterated over within a call to .forEach().
For the case where you execute [].slice.call(array), all you're doing is making a shallow copy of all the indices of the array. This allows you to iterate over the copy's indices while removing the nodes from the original.
Below is a comprehensive example, but make sure your browser supports ES6 template strings.
Demo
var array = [0, 1, 2, 3, 4, 5, 6, 7];
document.write(`<p>original.forEach()</p>`);
array.forEach(function(num, index) {
document.write(`<pre>num: ${num}, index: ${index}, array: [${array}]</pre>`);
array.splice(index, 1);
});
document.write(`<pre>result: [${array}]</pre>`);
array = [0, 1, 2, 3, 4, 5, 6, 7];
var copy = array.slice();
document.write(`<p>copy.forEach()</p>`);
copy.forEach(function(num, index) {
document.write(`<pre>num: ${num}, index: ${index}, array: [${array}]</pre>`);
array.splice(array.indexOf(num), 1); // removing by reference, not by index
});
document.write(`<pre>result: [${array}]</pre>`);
body > * {
padding: 0;
margin: 0;
}

Lodash difference between _.remove() and _.pullAt()

What is the difference between lodash _.remove() and _.pullAt() functions?
var arr1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
_.remove(arr1, function (item) {
return item == 1
});
var arr2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
_.pullAt(arr2, 1);
console.log(arr1.toString() + '\n' + arr2.toString());
// both result to [0,2,3,4,5,6,7,8,9,]
I've crated fiddle and read the description on the lodash site that states that _.remove()
Removes all elements from array that predicate returns truthy for and returns an array of the removed elements
and _.pullAt()
Removes elements from array corresponding to the given indexes and returns an array of the removed elements
Is there any difference at all? Or am I missing something?
Even your example made different things:
remove splices element by value, while pullAt by index.
Let's check it with different array [0, 3, 1, 1, 5]:
remove: [0, 3, 5] - all 1 items removed
pullAt: [0, 1, 1, 5] - arr[1] was spliced
You also can write other filters than compare by value with remove:
_.remove(arr, item => item % 2); // removes all odd numbers
_.remove(arr, user => user.deleted); // splice deleted users
_.remove(arr, item => item < 5); // and etc.

Categories

Resources