Map an array to set empty elements - javascript

Given:
let input = [0, 1, 2,,,,,7]
I want to get:
let output = [, 1, 22, 333, 4444, 55555, 666666, 7777777]
(i.e. value equal key times the key)
How can I map (or equivalent) input including empty values? If I do input.map() I will get [, 1, 22,,,,,7777777] because map will -of course- not iterate empty values. Data can be arbitrary, strings, objects, numbers, etc. Using numbers in this example for simplicity.

You can fill the array before applying a mapping function so that all indexes are iterated over, including empty ones.
let result = input.fill().map((_,index)=>{/*...*/});
The mapping function provided as the second argument to Array.from can be similarly used.
let result = Array.from({length: input.length}, (_, index)=>{/*...*/});
Spread syntax does not ignore empty slots, so we can create a copy of the array with spread syntax and map over that. This has an added advantage of having the elements at each index available as well.
let result = [...input].map((elem, idx)=>{/*...*/});

map() can't include empty values. w3schools
map() does not execute the function for array elements without values.
So, either iterate the array with a for-loop:
out = [];
for (var i = 0; i < input.length; i++) {
var item = input[i];
if (item != null)
out[i] = item.toString().repeat(item);
}
Or create another mapx() functor:
Array.prototype.mapx = function(fn) {
var out = [];
for (var i = 0; i < this.length; i++) {
var item = this[i];
// if (item == null) item = sherlockHolmesKnow();
out[i] = fn(item, i);
}
return out;
};
and apply on the input:
input.mapx( (val, index) => (val == null ? null : (val+'').repeat(val)) )
which yields ["", "1", "22", null, null, null, null, "7777777"].
Let's skip the AI part of clever guessing the numbers in the empty slots.

Here is another approach too verbose but it works, with for loop you can loop through null values
arr=[0, 1, 2,,,,,7]
res=[]
f=false
for(let i=0;i<arr.length-1;i++){
if(arr[i]!=undefined){
res.push(Number(String(arr[i]).repeat(arr[i])))
//f=false
}
if(arr[i]==undefined&&f==false){
n= arr[i-1]
f=true
res.push(Number(String(n+1).repeat(n+1)))}
if(f==true && arr[i]==undefined){
n=Number(res[res.length-1].toString().charAt(0))+1
res.push(Number(String(n).repeat(n)))
}
}
console.log(res)

Related

Write a function getDuplicates

Write a function getDuplicates that returns an array of all the elements that appear more than once in the initial items array (keeping the order). If an element appears many times, it should still be added to the result once.
This is my code
function getDuplicates(items) {
let result = [];
if (items === [0,0,0,0]) {return [0]}
for (let i = 0; i < items.length; i++) {
for (let j = i + 1; j < items.length; j++) {
if (items[i] === items[j]) {
result.push(items[i])
}
}
}
return result
}
I get an error:
input: [0, 0, 0, 0]
Hide details
Expected:
[0]
Received:
[0,0,0,0,0,0]
In JavaScript, arrays are objects, so when you use the === operator to compare two arrays, it will only return true if they are the exact same object in memory.
Use a Set to track duplicates: Instead of using an array to store the duplicate elements, we can use a Set to make sure we don't add duplicates to the result array. A Set is an efficient data structure for checking if an element exists or not, and it also automatically removes duplicates.
Use a single loop: Instead of using two nested loops to compare every element with every other element, we can use a single loop to keep track of the elements we've seen so far, and add them to the result if we see them again.
function getDuplicates(items) {
const result = [];
const seen = new Set();
for (const item of items) {
if (seen.has(item) && !result.includes(item)) {
result.push(item);
} else {
seen.add(item);
}
}
return result;
}
console.log(getDuplicates([0, 1, 0, 1, 2]))
a modified version of yours
function getDuplicates(items) {
let result = [];
let added = {};
for (let i = 0; i < items.length; i++) {
if (!added[items[i]] && items.indexOf(items[i], i + 1) !== -1) {
result.push(items[i]);
added[items[i]] = true;
}
}
return result;
}
console.log(getDuplicates([0, 1, 0, 1, 2]))
or in short doing the same
const getDuplicates = items => items.filter((item, index) => items.indexOf(item) !== index && items.lastIndexOf(item) === index);
console.log(getDuplicates([0, 1, 0, 1, 2]))
The best way to filter out the unique elements in an array is JavaScript Set
You cannot compare two arrays just like array1 === array2 because, Arrays have the type Object and you cannot compare two object just with equal to operator. Objects are not compared based on their values but based on the references of the variables. So when you compare two arrays which have same values using array1 === array2, it will compare its memory location only, not its values. So it will be only false.
The best way to achieve your result is to create an Array by checking the number of occurrences of nodes in the parent array, having occurrences count more than one and use a Set to remove the repetitions
function getDuplicates(items) {
return Array.from(new Set(items.filter(node => items.filter(x => node === x).length > 1)))
}
console.log(getDuplicates([0, 1, 0, 1, 2]))
You can try it:
Check if the current number is duplicated by using filter to check the length of an array.
Check if the result array contains duplicates.
function getDuplicates(items) {
let result = [];
for (let i = 0; i < items.length; i++) {
if ((items.filter(item => item == items[i])).length > 1 && !result.includes(items[i])) {
result.push(items[i]);
}
}
return result;
}
console.log(getDuplicates([0, 0, 0, 0]));
So. first of all - comparing 2 array will not work, (Somebody already explained why above).
Your code doesn't work because of if statement. You're checking if an array doesn't have any value except 0.
Try summing all numbers in the array and check if it's 0.
if(arr.reduce((accum, curr) => return accum += curr) == 0) {
return [0];
}
Your code is close, but there are a few issues that need to be addressed. First, you should not use the strict equality operator === to compare arrays, because it checks whether the two arrays have the same reference, not the same elements. Instead, you can use the JSON.stringify() method to compare the string representations of the arrays.
Second, your code only returns [0] if the input array is [0,0,0,0], which is not a general solution for finding duplicates. You can use an object to keep track of the count of each element in the array, and then add the elements that have a count greater than 1 to the result array.
Here's the corrected code:
function getDuplicates(items) {
let result = [];
let count = {};
for (let i = 0; i < items.length; i++) {
if (count[items[i]] === undefined) {
count[items[i]] = 1;
} else {
count[items[i]]++;
}
}
for (let i = 0; i < items.length; i++) {
if (count[items[i]] > 1 && result.indexOf(items[i]) === -1) {
result.push(items[i]);
}
}
return result;
}
This code keeps track of the count of each element in the count object, and then adds the elements that have a count greater than 1 to the result array, while making sure not to add duplicates to the result.

Why can I not concat an array to the result of a filter?

I'm a bit curious why the behaviors are different between the two solutions posted below. In the Failing solution, I've concated the zeros array to what I assume by the time of execution, would be the result array of the filter operation. I'm curious why the result is not the updated concated variant (an array with 0s at the end) and instead if simply the initial output of the filter operation.
Passing:
const moveZeros = function (arr) {
let zeros = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === 0) zeros.push(0);
}
let filteredArray = arr.filter( element => element !== 0).concat(zeros)
return filteredArray;
//returns [1,2,3,0,0,0]
}
Failing:
const moveZeros = function (arr) {
let zeros = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === 0) zeros.push(0);
}
let filteredArray = arr.filter( element => element !== 0);
// shouldnt the line below concat zeros to the filter result?
filteredArray.concat(zeros);
return filteredArray;
//returns [1,2,3]
}
This also passes:
return filteredArray.concat(zeros)
concat() doesn't modify the array in place, it returns a new array. Your failing version doesn't return the new array, it returns the original array.
Array.concat() return the concatenated array instead of the original.
let arr = [1,0,0,2,3,0];
let zeros = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === 0) zeros.push(0);
}
let filteredArray = arr.filter( element => element !== 0);
console.log(filteredArray);
let concatenatedArray = filteredArray.concat(zeros);
console.log(concatenatedArray);
So you need to reassign filteredArray like:
filteredArray = filteredArray.concat(zeros);
From the MDN Web Docs
The concat() method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.
In your passing solution you are assigning the result of a .concat() to a variable, and then returning that variable, whereas in your failing solution, you are returning the original array, because you did not assign the result of filteredArray.concat(zeros) to anything

How to append two element in array?

I am pushing element in the array using javascript .
and i am getting output like this
["api", "management", "provision", "tenant", "external", "provider"] => Correct
after pushing the data into array now i want append two element from the array management and provision and want output like this
["api", "management/provision", "tenant", "external", "provider"]
how would i do this ?
any example would be good for me
thanx in advance
The simplest thing you can do is to remove them both, join with / and put at the right place. You can do this in a few lines of code:
const input = ["api", "management", "provision", "tenant", "external", "provider"];
input.splice(1, 3, input.slice(1, 3).join('/'));
// now input contains ["api", "management/provision", "external", "provider"]
This can be further made more readable and reusable:
function mergeTerms(startIndex, endIndex, array) {
const input = array.slice(0); // make a shallow copy of the array in order not to mutate it
input.splice(startIndex, endIndex, input.slice(startIndex, endIndex).join('/'));
return input;
}
and then:
mergeTerms(1, 3, input);
Lets say its the var array that holds the values.
var temp = array.splice(2,3);
array[1] = array[1]+"/"+temp;
function mergeArrayEntries(e1, e2, arr) {
var index = -1;
for (var i = 0; i < arr.length; i++) {
if (arr[i] == e1) {
index = i;
}
if (arr[i] == e2 && index > -1) {
arr[index] = arr[index]+"/"+arr[i];
arr.splice(i, 1);
}
}
}
this function searches for e1 and e2 in the arr and once found, it merges them to position of e1 and deletes e2 entry in arr.
hope it helps
Not the nicest code, and not at all reusable, but will give you what you are looking for --- just another approach
var array = ["api", "management", "provision", "tenant", "external", "provider"];
var subArray = [];
subArray.push(array[1]);
subArray.push(array[2])
array.splice(1, 2);
subArray = subArray.join("/")
array.splice(1, 0, subArray);

Get the array index of duplicates

In a JavaScript array how can I get the index of duplicate strings?
Example:
MyArray = ["abc","def","abc"]; //----> return 0,2("abc");
Another example:
My Array = ["abc","def","abc","xyz","def","abc"]
//----> return 0,2,5("abc") and 1,4("def");
I have no idea how to do this.
Thanks in advance for your help!
Update 01/2022: It's not 2013 anymore, and many things have changed. I neither recommend modifying the prototype, nor is the approach in this answer the "best" as it requires several iterations over the array.
Here's an updated version of the original answer, retaining its spirit, as well as the original answer below.
function getDuplicates<T>(input: T[]): Map<T, number[]> {
return input.reduce((output, element, idx) => {
const recordedDuplicates = output.get(element);
if (recordedDuplicates) {
output.set(element, [...recordedDuplicates, idx]);
} else if (input.lastIndexOf(element) !== idx) {
output.set(element, [idx]);
}
return output;
}, new Map<T, number[]>());
}
Yet another approach:
Array.prototype.getDuplicates = function () {
var duplicates = {};
for (var i = 0; i < this.length; i++) {
if(duplicates.hasOwnProperty(this[i])) {
duplicates[this[i]].push(i);
} else if (this.lastIndexOf(this[i]) !== i) {
duplicates[this[i]] = [i];
}
}
return duplicates;
};
It returns an object where the keys are the duplicate entries and the values are an array with their indices, i.e.
["abc","def","abc"].getDuplicates() -> { "abc": [0, 2] }
Another less sophisticated approach:
Iterate over the whole array and keep track of the index of each element. For this we need a string -> positions map. An object is the usual data type to use for this. The keys are the elements of the array and the values are arrays of indexes/positions of each element in the array.
var map = {};
for (var i = 0; i < arr.length; i++) {
var element = arr[i]; // arr[i] is the element in the array at position i
// if we haven't seen the element yet,
// we have to create a new entry in the map
if (!map[element]) {
map[element] = [i];
}
else {
// otherwise append to the existing array
map[element].push(i);
}
// the whole if - else statement can be shortend to
// (map[element] || (map[element] = [])).push(i)
}
Now you can iterate over the map and remove all entries where the array value has a length of one. Those are elements that appear only once in an array:
for (var element in map) {
if (map[element].length === 1) {
delete map[element];
}
}
Now map contains a string -> positions mapping of all duplicate elements of the array. For example, if you array is ["abc","def","abc","xyz","def","abc"], then map is an object of the form
var map = {
'abc': [0,2,5],
'def': [1,4]
};
and you can process it further in any way you like.
Further reading:
Eloquent JavaScript - Data structures: Objects and Arrays
MDN - Working with objects
MDN - Predefined core objects, Array object
This covers finding the indices efficiently:
var inputArray = [1, 2, 3, 4, 5, 6, 6, 7, 8, 9];
var encounteredIndices = {};
for(var i = 0; i < inputArray.length; i++)
if (encounteredIndices[inputArray[i]])
console.log(i); // Or add to some array if you wish
else
encounteredIndices[inputArray[i]] = 1;

Delete zero values from Array with JavaScript

I have an array with name "ids" and some values like ['0','567','956','0','34']. Now I need to remove "0" values from this array.
ids.remove ("0"); is not working.
Here's a function that will remove elements of an array with a particular value that won't fail when two consecutive elements have the same value:
function removeElementsWithValue(arr, val) {
var i = arr.length;
while (i--) {
if (arr[i] === val) {
arr.splice(i, 1);
}
}
return arr;
}
var a = [1, 0, 0, 1];
removeElementsWithValue(a, 0);
console.log(a); // [1, 1]
In most browsers (except IE <= 8), you can use the filter() method of Array objects, although be aware that this does return you a new array:
a = a.filter(function(val) {
return val !== 0;
});
Use splice method in javascript. Try this function:
function removeElement(arrayName,arrayElement)
{
for(var i=0; i<arrayName.length;i++ )
{
if(arrayName[i]==arrayElement)
arrayName.splice(i,1);
}
}
Parameters are:
arrayName:- Name of the array.
arrayElement:- Element you want to remove from array
Here's one way to do it:
const array = ['0', '567', '956', '0', '34'];
const filtered = array.filter(Number);
console.log(filtered);
For non-trivial size arrays, it's still vastly quicker to build a new array than splice or filter.
var new_arr = [],
tmp;
for(var i=0, l=old_arr.length; i<l; i++)
{
tmp = old_arr[i];
if( tmp !== '0' )
{
new_arr.push( tmp );
}
}
If you do splice, iterate backwards!
For ES6 best practice standards:
let a = ['0','567','956','0','34'];
a = a.filter(val => val !== "0");
(note that your "id's" are strings inside array, so to check regardless of type you should write "!=")
Below code can solve your problem
for(var i=0; i<ids.length;i++ )
{
if(ids[i]=='0')
ids.splice(i,1);
}
ids.filter(function(x) {return Number(x);});
I believe, the shortest method is
var newList = ['0', '567', '956', '0', '34'].filter(cV => cV != "0")
You could always do,
listWithZeros = ['0', '567', '956', '0', '34']
newList = listWithZeros.filter(cv => cv != "0")
The newList contains your required list.
Explanation
Array.prototype.filter()
This method returns a new array created by filtering out items after testing a conditional function
It takes in one function with possibly 3 parameters.
Syntax:
Array.prototype.filter((currentValue, index, array) => { ... })
The parameters explain themselves.
Read more here.
The easy approach is using splice!!. But there's a problem, every time you remove an element your array size will constantly reduce. So the loop will skip 1 index the array size reduces.
This program will only remove every first zero.
// Wrong approach
let num = [1, 0, 0, 2, 0, 0, 3,];
for(let i=0; i<num.length; i++){
if(num[i]==0)
num.splice(i, 1);
}
console.log(num)
the output will be
[1,0,2,0,3]
So to remove all the zeros you should increase the index if you found the non-zero number.
let i = 0;
while(i<num.length){
if(num[i]==0){
num.splice(i,1);
}
else{
i++;
}
}
But there's a better way. Since changing the size of the array only affects the right side of the array. You can just traverse in reverse and splice.
for(let i=num.length-1; i>=0; i--){
if(num[i]===0)
num.splice(i,1);
}

Categories

Resources