Removing values in a range from an array - javascript

I want to remove values in a range from an array. For example, removeVals([20, 30, 40, 50, 60, 70], 2, 4) should return the array [20, 30, 70]. How can I solve this problem?

This can be done in one-liner. If you're unfamiliar with arrow functions this might be a bit confusing but I'll put my solution out there anyway.
var removeVals = (array, start, end) => array.filter((item, index) => index < start || index > end);
console.log(removeVals([20, 30, 40, 50, 60, 70], 2, 4)) // [20, 30, 70]
JavaScript's built-in filter function iterates through an array, and passes each item (and the index of said item optionally) into the function that it's provided. If the return value of that function is true, then the item stays in the array, otherwise it is removed. The function that we pass into the filter function only returns true if the index of the current item in the array is less than the beginning of the range or more that the end of the range, therefore removing items that are in the range.

You can use Array#splice, which changes the input array. So you would need to return the modified array.
DEMO
const removeVals = (arr, start, end) => arr.splice(start, end-start+1) && arr;
console.log( removeVals([20, 30, 40, 50, 60, 70], 2, 4) );

This solution works like .filter() demonstrated in tybocopperkettle's answer, but with .flatMap() instead. Using a ternary in .flatMap() gives us an advantage of returning almost any value.
idx < a || idx > z ? num : []
JavaScript
Description
idx < a
If index is less than start...
||
...OR...
idx > z
...if index is greater than end...
? num
...return the value...
:[]
...otherwise return nothing🞾
🞾[] returns as nothing since .flatMap() applies .flat() to whatever it returns.
const arrayA = [20, 30, 40, 50, 60, 70];
const Aa = 2;
const Az = 4;
const arrayB = ['A', 'B', 'C', 'D', 'E', 'F'];
const Ba = 0;
const Bz = 7;
const remVal = (array, a, z) => array
.flatMap((num, idx) =>
idx < a || idx > z ?
num : []
);
console.log(remVal(arrayA, Aa, Az));
console.log(remVal(arrayB, Ba, Bz));

Method-1
This method removes the subset in the range Array[startIx, stopIx] from the source array using the Array.prototype.splice()method.
// INPUT → array[0, array.length - 1]
// OUTPUT → array[0, startIx - 1] U array[stopIx + 1, array.length - 1]
let removeVals = (array, startIx, stopIx) => {
array.splice(startIx, stopIx - startIx + 1);
return array;
}
let array= [20, 30, 40, 50, 60, 70]
console.log(`Result: ${removeVals(array, 2, 4)}`);
Method-2
Create a new array inside the function.
Add the values in the range array[0, startIx - 1] to the new array.
Add values from range array[stopIx+ 1, array.lenght - 1] to the new array.
// INPUT → array[0, array.length - 1]
// OUTPUT → array[0, startIx - 1] U array[stopIx + 1, array.length - 1]
let removeVals = (array, startIx, stopIx) => {
let resultArray = []
for(let i = 0; i < startIx ; ++i)
resultArray.push(array[i])
for(let i = stopIx + 1 ; i < array.length ; ++i)
resultArray.push(array[i])
return resultArray;
}
let array= [20, 30, 40, 50, 60, 70]
console.log(`Result: ${removeVals(array, 2, 4)}`);

Related

Javascript : remove an item in an array using the given start index and end index parameters

"Given array, start index and end index, remove values in that given index range,hence shortening the array.For example, removeVal([20,30,40,50,60,70],2,4) should return [20,30,70]"
I can output [20,30], meaning that my code already can remove 40,50,60 in the array. However, I think I might be incorrect on my if statement since I cannot include '70' on the final output. Thank you in advance.
function removeVal(arr,start,end){
//For loop
for(let i=0; i< arr.length; i++){
if(arr[i] >= arr[start] && arr[i] <= arr[end]){
arr.splice(i);
}
}
return arr;
}
//2,4 is the start and end index of the array. example Start index is arr[2] which is equal to 40 and End index is arr[4] which is equal to 60
y =removeVal([20,30,40,50,60,70],2,4);
console.log(y);
You can use the splice function, since all array elements being removed are consecutive:
function removeVal(arr, start, end) {
// since the splice function mutates the variable
// copy the arr into a new variable
// and mutate that instead
const newArr = arr
// you need to add 1 to the difference
// because the last element of the difference
// would not be included otherwise
newArr.splice(start, (end-start+1))
return newArr
}
You could take the items with smaller index than start or greater index than end.
function removeIndices(array, start, end) {
return array.filter((_, i) => i < start || i > end);
}
console.log(removeIndices([20, 30, 40, 50, 60, 70], 2, 4));
function removeIndices(array, start, end) {
const result = [];
for (let i = 0; i < array.length; i++) {
if (i < start || i > end) result.push(array[i]);
}
return result;
}
console.log(removeIndices([20, 30, 40, 50, 60, 70], 2, 4));
If you want to keep your original array, this is possible too :
let originalArray = new Array(20,30,40,50,60,70);
let backupOriginal = originalArray.slice();
originalArray.splice(2,3);
console.log(originalArray); //output : [ 20, 30, 70 ]
console.log(backupOriginal); //output : [ 20, 30, 40, 50, 60, 70 ]

How to Change a single Array into array of object [duplicate]

How do I succinctly write a function such that it creates a new array of object using every pair of elements from an array?
Assume even number of elements.
Example input:
input = [1, 42, 55, 20, 3, 21]
Output:
output = [{x:1, y:42}, {x:55, y:20}, {x:3, y:21}]
Edit:
This is the current solution I have which I am not a fan of:
[1, 42, 55, 20, 3, 21].reduce(
(acc, curr, i) => (
i % 2 === 0
? [...acc, { x: curr }]
: [...acc.slice(0, -1), { x: acc[acc.length - 1].x, y: curr }]), []
)
You can use a for loop which increment by the value of 2
const input = [1, 42, 55, 20, 3, 21];
const res = [];
for(let i = 0; i < input.length; i+=2){
res.push({x:input[i], y: input[i + 1]});
}
console.log(res)
I think breaking it into two steps helps with readability but it is marginally less efficient.
[1,42,55,20,3,21]
.map((n, i, arr) => ({ x: n, y: arr[i + 1] }))
.filter((n, i) => i % 2 === 0);
You can just iterate the array. For odd length last value won't be paired, since no pair is available
const array = [1, 42, 55, 20, 3, 21];
var output = [];
for (index = 0; index < array.length-1; index+=2) {
output.push({x:array[index], y:+array[index+1]});
}
console.log(output);
I think a simplification of your technique is readable enough:
const toPoints = coordinates =>
coordinates .reduce (
(acc, curr, i, all) => (i % 2 === 0 ? acc : [...acc, { x: all[i - 1], y: curr }]),
[]
)
console .log (toPoints ([1, 42, 55, 20, 3, 21]))
We simply add the next pair only on the even indices. Of course this will fail if you want an odd-length array to end up with a final object with an x- but not a y- property.
An approach which has benefit of being easy to reason about:
const arr = [1,42,55,20,3,21];
const pairs = [...Array(arr.length/2).keys()].map(c => ({x: arr[2*c], y: arr[2*c + 1]}));

Find the sum of the first n num [duplicate]

This question already has answers here:
Javascript - Counting array elements by reduce method until specific value occurs doesn't give a correct output
(4 answers)
Closed 2 years ago.
I have an array with numbers. Find the sum of the first N elements to the first zero. Task must be completed with
Example: - summarize the first 3 elements, because next is the element with the number 0.
You could do this as follows:
let arr = [10, 20, 3, 0, 16, 35, 1];
let sum = arr.slice(0, arr.indexOf(0)).reduce((sum, v) => sum + v);
console.log(sum);
I first extract the numbers in front of the first zero using Array.slice(). Then I use Array.reduce() to compute the sum of these numbers.
You can not break the iteration of reduce(). You can use a flag variable based on which you can add value to sum.
Try the following way:
let arr = [10, 20, 3, 0, 16, 35, 1];
let flag = true;
let sumNum = arr.reduce((sum, elem) => {
if (elem == 0) {
flag = false;
};
if(flag) return sum + elem;
else return sum + 0;
}, 0)
console.log(sumNum)
You can utilize an external variable stopCounting to flag if the counting should continue or not.
let arr = [10, 20, 3, 0, 16, 35, 1];
let stopCounting = false;
let sumNum = arr.reduce((sum, elem) => {
if (elem == 0) {
stopCounting = true;
}
return stopCounting ? sum : sum + elem;
}, 0);
console.log(sumNum);
You could iterate with a short circuit and check the value and add the value if not zero.
This approach does not search for zero in advance and needs only a single loop in the worst case.
var array = [10, 20, 3, 0, 16, 35, 1],
sum = 0;
array.every(v => (sum += v, v));
console.log(sum);
const arr = [10, 20, 3, 0, 16, 35, 1];
const zeroIndex = arr.indexOf(0);
const total = arr.slice(0, zeroIndex > 0 ? zeroIndex : arr.length)
.reduce(sum, n => sum+n, 0);
console.log(total);

How to filter an array based on a range and then take an additional sample either side of result

I am looking for a simple solution to the following example:
let rangeOfInterest = [25 , 44];
let input = [10, 20, 30, 40, 50, 60];
I'm interested in all values that are greater than 25 and less than 44 (inclusive). The rangeOfInterest may be completely inside or completely outside the input values, other examples include [85, 95] or [0, 100].
output1 = [30, 40];
If a value exists either side of this output then take that sample as well;
finalOutput = [20, 30, 40, 50];
I can achieve the above by applying a filter to the array then finding the index of the first and last elements of the result and extracting the additional samples based on that (if they exist). Is there a cleaner way of achieving this that doesn't involve ~20 lines of code?
Note: samples will be floats, used ints for a simpler example.
You can find the index of the first item that is larger than the minimum range, and the index of the first item that is larger than the maximum range, and slice according to the indexes (minIndex - 1, maxIndex + 1).
const fn = ([min, max], arr) => {
const startIndex = arr.findIndex(n => n > min); // find the index of the first item that is larger than min
const endIndex = arr.findIndex(n => n > max); // find the index of the first item that is smaller than max
return arr.slice(
startIndex > 1 ? startIndex - 1 : 0,
endIndex === -1 ? arr.length : endIndex + 1
);
};
const input = [10, 20, 30, 40, 50, 60];
console.log(fn([25 , 44], input));
console.log(fn([25 , 65], input));
console.log(fn([-25 , 65], input));
Try this:
let input = [10, 20, 30, 40, 50, 60];
let rangeOfInterest = [25 , 44];
let newOutput = input.filter(function(number) {
return Math.min(...rangeOfInterest) <= number && Math.max(...rangeOfInterest) >= number;
});
newOutput.push( Math.floor(Math.min(...rangeOfInterest) / 10) * 10 ); //adding 20
newOutput.push( Math.floor(Math.max(...rangeOfInterest) / 10) * 10 ); // adding 40
console.log(newOutput)
let roi = [25 , 44]; //simplifying range of interest variable name
let arr = [10, 20, 30, 40, 50, 60];
function inRange(val1,val2){//assuming val1<val2 always
return (num)=>{
return num>=val1 && num<=val2;
}
}
let firstInd=0;
let lastInd=0;
var resultArr = arr.filter((val,ind) => {
let match = inRange(roi[0],roi[1])(val);
if(!firstInd){
firstInd=match?ind:0;
}
lastInd = match&&(ind>lastInd)?ind:lastInd;
return match;
});
lastInd<arr.length?resultArr.push(arr[lastInd+1]):'';
firstInd>0?resultArr.splice(0,0,arr[firstInd-1]):'';
console.log(resultArr);

Sorting using two arrays

There are two arrays:
The first one contain numbers, and the second one contains "weight" of the first array values.
It works like this:
arr1 = [56,65,100,89,180,90];
"Weight" of the numbers are calculated in this way:
56 = 5+6 = 11;
65 = 6+5 = 11;
100 = 1+0+0 = 1; and so on..
So, arr2 = [11,11,1,17,9,9];
My question is how can I sort the values of the arr1 according to values of arr2?
I tried to modify simple bubble sort for this problem, but nothing changed.
function bubble(arr1, arr2) {
var len = arr1.length;
for (var i = 0; i < len; i++) {
for (var j = 0; j < len - i - 1; j++) {
if (arr2[j] > arr2[j + 1]) {
var temp = arr1[j];
arr1[j] = arr1[j + 1];
arr1[j + 1] = temp;
}
}
}
return arr1;
}
arr1 = [56, 65, 100, 89, 180, 90];
arr2 = [11, 11, 1, 17, 9, 9];
console.log(bubble(arr1, arr2));
I expect the output of the bubble function to be [100,180,90,56,65,89].
This is why:
FirstArray - [56,65,100,89,180,90] - arr1
"Weight of the values"[11,11, 1, 17, 9, 9 ] - arr2
Output [100,180,90,56,65,89]
[1, 9, 9 ,11,11,17]
You can just calculate the weight on the fly while sorting:
const arr = [56,65,100,89,180,90];
arr.sort( (a,b) =>
(a + '').split( '' ).reduce( (sum,x) => sum + +x, 0 ) -
(b + '').split( '' ).reduce( (sum,x) => sum + +x, 0 )
);
console.log( arr );
To achieve expected result, use below option of sorrting arr1 with logic mentioned in question
Sort arr1 bycomparing sum of digits
Convert number to string and split it to array
Use reduce sum all the digits and compare with the array elements
var arr1 = [56, 65, 100, 89, 180, 90];
var arr2 = [11, 11, 1, 17, 9, 9];
console.log(
arr1.sort(
(a, b) =>
a
.toString()
.split("")
.reduce((acc, v) => parseInt(acc) + parseInt(v)) -
b
.toString()
.split("")
.reduce((acc, v) => parseInt(acc) + parseInt(v))
)
);
codepen - https://codepen.io/nagasai/pen/WNeoaEv?editors=1010

Categories

Resources