Replace duplicates items in array with different values - javascript

i would like to Replace duplicates items with different values.
eg arr = [1,1,1,1,2,2,2,3] i want to replace the duplicates with R
So the result looks like this arr = [1,R,R,R,2,R,R,3]
right now I'm using this approach:
arr = [1,1,1,1,2,2,2,3]
let previous = 0;
let current = 1;
while (current < arr.length) {
if (arr[previous] === arr[current]) {
arr[current] = 'R';
current += 1;
} else if (arr[previous] !== arr[current]) {
previous = current;
current += 1;
}
}
i wondering if there is different approach for to achieve that. for Example using Lodash (uniqwith, uniq).
Thanks

here's how I'd do it
It look if the current element is the first of the array with the current value and replace it if not
It may take some times on very big arrays
const input = [1,1,1,1,2,2,2,3]
let output = input.map(
(el, i) => input.indexOf(el) === i ? el : 'R'
)
console.log(output)

You could take a closure over a Set and check if the value is already seen or not.
let array = [1, 1, 1, 1, 2, 2, 2, 3],
result = array.map((seen => v => seen.has(v) ? 'R' : (seen.add(v), v))(new Set));
console.log(...result);
A check previous value approach
let array = [1, 1, 1, 1, 2, 2, 2, 3],
result = array.map((v, i, { [i - 1]: l }) => l === v ? 'R' : v);
console.log(...result);

This is actually very simple to do by using sets (Set).
const initialArray = [1,1,1,1,2,2,2,3];
const valuesSet = new Set();
const newArray = initialArray.map((value) => {
if (valuesSet.has(value)) {
return 'R';
} else {
valuesSet.add(value);
return value;
}
});

Related

Identifying non-matches in two javascript arrays [duplicate]

I was wondering how I'd go about implementing a method in javascript that removes all elements of an array that clear a certain condition. (Preferably without using jQuery)
Ex.
ar = [ 1, 2, 3, 4 ];
ar.removeIf( function(item, idx) {
return item > 3;
});
The above would go through each item in the array and remove all those that return true for the condition (in the example, item > 3).
I'm just starting out in javascript and was wondering if anyone knew of a short efficient way to get this done.
--update--
It would also be great if the condition could work on object properties as well.
Ex.
ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
ar.removeIf( function(item, idx) {
return item.str == "c";
});
Where the item would be removed if item.str == "c"
--update2--
It would be nice if index conditions could work as well.
Ex.
ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
ar.removeIf( function(item, idx) {
return idx == 2;
});
You can use Array filter method.
The code would look like this:
ar = [1, 2, 3, 4];
ar = ar.filter(item => !(item > 3));
console.log(ar) // [1, 2, 3]
You could add your own method to Array that does something similar, if filter does not work for you.
Array.prototype.removeIf = function(callback) {
var i = 0;
while (i < this.length) {
if (callback(this[i], i)) {
this.splice(i, 1);
}
else {
++i;
}
}
};
To me, that's one of the coolest features of JavaScript. Ian pointed out a more efficient way to do the same thing. Considering that it's JavaScript, every bit helps:
Array.prototype.removeIf = function(callback) {
var i = this.length;
while (i--) {
if (callback(this[i], i)) {
this.splice(i, 1);
}
}
};
This avoids the need to even worry about the updating length or catching the next item, as you work your way left rather than right.
You can use Array.filter(), which does the opposite:
ar.filter(function(item, idx) {
return item <= 3;
});
You can use lodash.remove
var array = [1, 2, 3, 4];
var evens = _.remove(array, function(n) {
return n % 2 == 0;
});
console.log(array);
// => [1, 3]
console.log(evens);
// => [2, 4]
Make it a one-liner with arrow function:
ar = ar.filter(i => i > 3);
simply write the following example if condition could work on object properties as well
var ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
var newArray = [];
for (var i = 0, len = ar.length; i<len; i++) {
if (ar[i].str == "b")
{newArray.push(ar[i]);};
};
console.log(newArray);
See the example Live Example
if you need to remove exactly one item, and you know for sure that the item exists, you can use this one-liner:
ar.splice(ar.findIndex(el => el.id === ID_TO_REMOVE), 1);
// or with custom method:
let ar = [ {id:1, str:"a"}, {id:2, str:"b"}, {id:3, str:"c"}, {id:4,str:"d"} ];
ar.removeById = id => ar.splice(ar.findIndex(el => el.id === id), 1);
ar.removeById(ID_TO_REMOVE);
http://jsfiddle.net/oriadam/72kgprw5/
ES6 only
I love these kinds of questions and just a different version from me too... :)
Array.prototype.removeIf = function(expression) {
var res = [];
for(var idx=0; idx<this.length; idx++)
{
var currentItem = this[idx];
if(!expression(currentItem))
{
res.push(currentItem);
}
}
return res;
}
ar = [ 1, 2, 3, 4 ];
var result = ar.removeIf(expCallBack);
console.log(result);
function expCallBack(item)
{
return item > 3;
}
My solution for an array of numbers would be:
ar = ar.filter(item => item < 4);
For the in-place remove, my solution is
ar.filter(item => !(item > 3))
.forEach(obsoleteItem => ar.splice(ar.indexOf(obsoleteItem), 1));
Incorrect way
First of all, any answer that suggests to use filter does not actually remove the item. Here is a quick test:
var numbers = [1, 2, 2, 3];
numbers.filter(x => x === 2);
console.log(numbers.length);
In the above, the numbers array will stay intact (nothing will be removed). The filter method returns a new array with all the elements that satisfy the condition x === 2 but the original array is left intact.
Sure you can do this:
var numbers = [1, 2, 2, 3];
numbers = numbers.filter(x => x === 2);
console.log(numbers.length);
But that is simply assigning a new array to numbers.
Correct way to remove items from array
One of the correct ways, there are more than 1, is to do it as following. Please keep in mind, the example here intentionally has duplicated items so the removal of duplicates can be taken into consideration.
var numbers = [1, 2, 2, 3];
// Find all items you wish to remove
// If array has objects, then change condition to x.someProperty === someValue
var numbersToRemove = numbers.filter(x => x === 2);
// Now remove them
numbersToRemove.forEach(x => numbers.splice(numbers.findIndex(n => n === x), 1));
// Now check (this is obviously just to test)
console.log(numbers.length);
console.log(numbers);
Now you will notice length returns 2 indicating only numbers 1 and 3 are remaining in the array.

How to compare two arrays and then return the sum of all elements of the array before the changed element of the array

I have two arrays that I need to check the difference upon and return the sum of all elements of the array before the changed element and includes him.
I currently have two arrays of area height that get updated when the input's value is changed. Also can be changed 2 or more elements of array, then need sum all changed elements and all elements before last changed element.
For example arrays:
let oldArea = [3, 4, 2]
let newArea = [3, 6, 2]
I tried something like this (it does its job partially, but the array length can be 5 or more elements, so this solution is bad) :
let oldArea = [3, 4, 2]
let newArea = [3, 6, 2]
let changedArea = [];
if (
oldArea[0] !== newArea[0] &&
oldArea[1] === newArea[1]
) {
changedArea.push(newArea[0]);
} else if (
oldArea[1] !== newArea[1] &&
oldArea[0] === newArea[0] &&
oldArea[2] === newArea[2]
) {
changedArea.push(newArea[0] + newArea[1]);
} else changedArea.push(newArea.reduce((a, b) => a + b, 0));
let changedAreaHeight = changedArea.reduce((a, b) => a + b, 0);
console.log(changedAreaHeight)
Example
I will be grateful for any tips with other solutions.
You can use a simple for loop and break when the elements are not same
let oldArea = [3, 4, 2]
let newArea = [3, 6, 2]
let final = 0;
for (let i = 0; i < newArea.length; i++) {
if (newArea[i] === oldArea[i]) {
final += newArea[i]
} else {
final += newArea[i]
break;
}
}
console.log(final)

How to multiply array values without nested loops

Problem:
Given an array of integers, return a new array such that each element at index i of the new array is the product of all the numbers in the original array except the one at i.
For example:
if our input was [1, 2, 3, 4, 5], the expected output would be [120, 60, 40, 30, 24].
If our input was [3, 2, 1], the expected output would be [2, 3, 6].
Solution 1 (With Nested loops): I'm able to solve this by nested loops like below:
const input = [1, 2, 3, 4, 5];
function output(items) {
const finalArray = [];
for (let i = 0; i < items.length; i++) {
let multipliedNum = 1;
items.forEach((item, indx) => {
if (i !== indx) {
multipliedNum = multipliedNum * item;
}
});
finalArray.push(multipliedNum)
}
return finalArray;
}
console.log(output(input))
I'm trying to find out another solution without nested loops inside output function? Any help or suggestion really appreciated.
If there are no zero values, you can loop through all the values once to get the product. Then just return the array where each the product is divided by each entry.
However, if there are zeros then there is a little more to be done to check how many there are. One zero is fine but more than 1 means that the value is zero for each entry.
const input = [1, 2, 3, 4, 5];
const input2 = [1, 2, 3, 4, 0];
const input3 = [1, 2, 3, 0, 0];
function output(items) {
let zeroCount = 0;
let totalProduct = 1;
for (let i = 0; i < items.length; i++) {
if (items[i] === 0) {
if (++zeroCount > 1) break;
continue;
}
totalProduct *= items[i];
}
if (zeroCount > 1) {
// more than 1 zero -> all values are 0
return new Array(items.length).fill(0);
} else if (zeroCount === 1) {
// only 1 zero -> only the value that is zero will be the totalProduct
return items.map(item => item === 0 ? totalProduct : 0);
}
// no zero in array -> divide the totalProduct by each item
return items.map(item => totalProduct / item);
}
console.log(output(input))
console.log(output(input2))
console.log(output(input3))
Based on what #Mike said in the comment here's the answer.
const input = [1, 2, 3, 4, 5];
const mulValues = input.reduce((acc, next) => acc * next);
const output = input.map(i => mulValues/i)
console.log(output)
you can do something like that (assuming array doesn't contain zero):
calculate product of all array elements
divide product by element at position [i] to get the desired output
const input = [1, 2, 3, 4, 5];
function output(items) {
const finalArray = [];
const multipliedNum=1;
for (let i = 0; i < items.length; i++) {
multipliedNum *= item[i];
}
for (let i = 0; i < items.length; i++) {
finalArray.push(multipliedNum/item[i]);
}
return finalArray;
}
console.log(output(input))
I know this has already been answered, but I think I have a better one.
If you take this issue by a different approach you will see that the product leaving the value at the index out, is also the product devided by value at the index.
If you know use the reduce function, you can simply calculate the product in one line using:
items.reduce((a, b) => a * b)
and then just divide by the value you want to ignore... like this:
items.reduce((a, b) => a * b) / items[index]
if you now want to compress this in one line instead of wrapping it into a for loop block you can simply copy the array and use the map function and the result could look like this:
result = [...items].map((v, i) => items.reduce((a, b) => a * b) / v)
I hope that this helps you to reduce your code

Check if array contains all elements of another array AND get the index in return

There is a lot of Questions about if an array contains all elements of another array and they return only true or false but i need the index of where it starts,
Example:
array1 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
array2 = [7,8,9,10,11];
It should be index = 6
Edit:I have a static or constant array with the following numbers: [2,5,10,5,5,5,8,1,4,6,2,7,6,3,8,2,4]
and i will get an array of numbers like this one: [2,8,3,8,4,2,3,2,2,4,2,8,2,6,2,5,10,5,5,5,8,1,4,6,2,7,6,2,7,6,3,8,2,4,2,3,7,3,12,3,8,2,2,6,3,2,3,2,9,2,5,2,3,5]
I need to find the sequence of numbers and the index of where it starts (in this case is 14).
I'm kind of new to programming that is why i'm asking for a simple solution with loops and if statements
I tried with something like this but it failed so bad
for (var i = 0; i < array_Input.length; i++) {
if (array_Input[i] == 2 && array_Input[i+1] == 5 && array_Input[i+2] == 10 && array_Input[i+3] == 5 && array_Input[i+4] == 5 && array_Input[i+5] == 5) {var index=+ 1;}
}
Note that i haven't tried comparing one array with the other one
Thank you all for your help
You can check if slices of array1 starting at various indices equal array2 using every:
function findIndex(a1, a2) {
for (var i = 0; i < a1.length - a2.length + 1; i++) {
if (a1.slice(i, i + a2.length).every((n, j) => n === a2[j])) return i;
}
return -1;
}
var array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
var array2 = [7, 8, 9, 10, 11];
console.log(findIndex(array1, array2));
you can check if array1 contains all values of array2 :
let array1 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
let array2 = [7,8,9,10,11];
let minOfArray2 = Math.min(...array2);
let flag = true;
let indexWhereItStarts;
let found = false;
array2.map( val => {
if(!array1.includes(val)) flag = false;
});
array1.map( (val, index) => {
if(val === minOfArray2) indexWhereItStarts = index;
});
console.log(flag);
console.log(indexWhereItStarts);
or you can check all with two one liner (reduce method) :
let array1 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
let array2 = [7,8,9,10,11];
let minOfArray2 = Math.min(...array2);
let flag2 = array2.reduce((acc,val) => array1.includes(val) ? acc && true : false, true);
let indexWhereItStarts2 = array1.reduce((acc, val, i) => val === minOfArray2 ? i : acc, 0);
console.log(flag2);
console.log(indexWhereItStarts2);

Reduce over a single array summing slices

I have an array of values
let a = [1,2,3,4,5,6];
I want to sum specific slices, for example a.[0] + a.[1] giving a new array:
[1 + 2, 3 + 4, 5 + 6]
Is there a recommended way to do this with reduce() or other method? Such as some kind of stepping/range parameter?
Because I want #T.J. Crowder to be right :)
const a = [1, 2, 3, 4, 5, 6];
// Loop over all values of the array
const res = a.reduce((tmp, x, xi) => {
// Use Math.floor and xi (the index of the value we are treating)
// to store the values on the returned array at the correct position
tmp[Math.floor(xi / 2)] = (tmp[Math.floor(xi / 2)] || 0) + x;
return tmp;
}, []);
console.log(res);
Will also work if the number of element is not pair
const a = [1, 2, 3, 4, 5];
const res = a.reduce((tmp, x, xi) => {
tmp[Math.floor(xi / 2)] = (tmp[Math.floor(xi / 2)] || 0) + x;
return tmp;
}, []);
console.log(res);
Alternative solution :
const a = [1, 2, 3, 4, 5, 6];
const res = [];
do {
res.push(a.splice(0, 2).reduce((tmp, x) => tmp +x, 0));
} while (a.length);
console.log(res);
You can do this with reduce, but it's not the right tool for the job. Here's how, keying off index and passing an array around:
let array = [1,2,3,4,5,6];
let result = array.reduce((a, v, i) => {
if (i % 2 == 1) {
// It's an odd entry, so sum it with the
// previous entry and push to the result array
a.push(v + array[i - 1]);
}
return a;
}, []);
console.log(result);
You can squash that into a concise arrow function, at the expense of clarity:
let array = [1,2,3,4,5,6];
let result = array.reduce((a, v, i) => ((i % 2 === 1 ? a.push(v + array[i - 1]) : 0), a), []);
console.log(result);
A simple for loop would probably be more appropriate, though:
let array = [1,2,3,4,5,6];
let result = [];
for (let n = 0; n < array.length; n += 2) {
result.push(array[n] + array[n + 1]);
}
console.log(result);
Another approach with Array#flatMap and taking only the odd indices for a value.
var array = [1, 2, 3, 4, 5, 6],
result = array.flatMap((v, i, { [i + 1]: w = 0 }) => i % 2 ? [] : v + w);
console.log(result);
A simple and quick solution with [Array.prototype.reduce] can look like this:
const array = [1,2,3,4,5,6];
const range = 2;
const result = array.reduce((all, item, i) => {
const idx = Math.floor(i/range);
if (!all[idx]) all[idx] = 0;
all[idx] += item;
return all;
},[]);
console.log(result);

Categories

Resources