This question already has answers here:
Flatten array of multiple nested arrays without recursion - javascript
(9 answers)
Closed last year.
I want to flatten an array with javascript but without recurssion and without prebuilt function.
This is the code but it dose not flatten the whole array and i want to know what is wrong with my code
input : [1, [2], [3,8, [[4]],9],[5,6]]
output : [1, 2, 3, 8, 5, 6]
Code :
flat = function(array) {
const output = []
for (let i = 0; i < array.length; i++) {
if (typeof array[i] == 'number') {
output.push(array[i])
} else {
let arr = array[i]
let n = 0
while (n < arr.length) {
if (typeof arr[n] == 'number') {
output.push(arr[n])
n++
} else {
arr = arr[n]
n--
console.log(arr, n);
}
}
}
}
return output
}
It's possible to do, but it involves managing a stack yourself, manually:
const input = [1, [2], [3, 8, [[4]], 9], [5, 6]];
const result = [];
const stack = [{current: input, pos: 0}];
while (stack.length > 0) {
let {current, pos} = stack.pop();
if (pos < current.length) {
let item = current[pos++];
stack.push({current, pos});
if (Array.isArray(item)) {
stack.push({current: item, pos: 0});
} else {
result.push(item);
}
}
}
console.log(result);
This is what a recursive approach would do in the background, more or less. If your concern about recursion was that you don't like/understand it, not sure that you will find this one more likeable.
Related
Given an array [[1, 7, 3, 8],[3, 2, 9, 4],[4, 3, 2, 1]],
how can I find the sum of its repeating elements? (In this case, the sum would be 10.)
Repeated values are - 1 two times, 3 three times, 2 two times, and 4 two times
So, 1 + 3 + 2 + 4 = 10
Need to solve this problem in the minimum time
There are multiple ways to solve this but time complexity is a major issue.
I try this with the recursion function
How can I optimize more
`
var uniqueArray = []
var sumArray = []
var sum = 0
function sumOfUniqueValue (num){
for(let i in num){
if(Array.isArray(num[i])){
sumOfUniqueValue(num[i])
}
else{
// if the first time any value will be there then push in a unique array
if(!uniqueArray.includes(num[i])){
uniqueArray.push(num[i])
}
// if the value repeats then check else condition
else{
// we will check that it is already added in sum or not
// so for record we will push the added value in sumArray so that it will added in sum only single time in case of the value repeat more then 2 times
if(!sumArray.includes(num[i])){
sumArray.push(num[i])
sum+=Number(num[i])
}
}
}
}
}
sumOfUniqueValue([[1, 7, 3, 8],[1, 2, 9, 4],[4, 3, 2, 7]])
console.log("Sum =",sum)
`
That's a real problem, I am just curious to solve this problem so that I can implement it in my project.
If you guys please mention the time it will take to complete in ms or ns then that would be really helpful, also how the solution will perform on big data set.
Thanks
I would probably use a hash table instead of an array search with .includes(x) instead...
And it's also possible to use a classical for loop instead of recursive to reduce call stack.
function sumOfUniqueValue2 (matrix) {
const matrixes = [matrix]
let sum = 0
let hashTable = {}
for (let i = 0; i < matrixes.length; i++) {
let matrix = matrixes[i]
for (let j = 0; j < matrix.length; j++) {
let x = matrix[j]
if (Array.isArray(x)) {
matrixes.push(x)
} else {
if (hashTable[x]) continue;
if (hashTable[x] === undefined) {
hashTable[x] = false;
continue;
}
hashTable[x] = true;
sum += x;
}
}
}
return sum
}
const sum = sumOfUniqueValue2([[1, 7, 3, 8],[[[[[3, 2, 9, 4]]]]],[[4, 3, 2, 1]]]) // 10
console.log("Sum =", sum)
This is probably the fastest way...
But if i could choose a more cleaner solution that is easier to understand then i would have used flat + sort first, chances are that the built in javascript engine can optimize this routes instead of running in the javascript main thread.
function sumOfUniqueValue (matrix) {
const numbers = matrix.flat(Infinity).sort()
const len = numbers.length
let sum = 0
for (let i = 1; i < len; i++) {
if (numbers[i] === numbers[i - 1]) {
sum += numbers[i]
for (i++; i < len && numbers[i] === numbers[i - 1]; i++);
}
}
return sum
}
const sum = sumOfUniqueValue2([[1, 7, 3, 8],[[[[[3, 2, 9, 4]]]]],[[4, 3, 2, 1]]]) // 10
console.log("Sum =", sum)
You could use an objkect for keeping trak of seen values, like
seen[value] = undefined // value is not seen before
seen[value] = false // value is not counted/seen once
seen[value] = true // value is counted/seen more than once
For getting a value, you could take two nested loops and visit every value.
Finally return sum.
const
sumOfUniqueValue = (values, seen = {}) => {
let sum = 0;
for (const value of values) {
if (Array.isArray(value)) {
sum += sumOfUniqueValue(value, seen);
continue;
}
if (seen[value]) continue;
if (seen[value] === undefined) {
seen[value] = false;
continue;
}
seen[value] = true;
sum += value;
}
return sum;
},
sum = sumOfUniqueValue([[1, 7, 3, 8], [3, 2, 9, 4], [4, 3, 2, 1]]);
console.log(sum);
Alternatively take a filter and sum the values. (it could be more performat with omitting same calls.)
const
data = [[1, 7, 3, 8], [3, 2, 9, 4, 2], [4, 3, 2, 1]],
sum = data
.flat(Infinity)
.filter((v, i, a) => a.indexOf(v) !== a.lastIndexOf(v) && i === a.indexOf(v))
.reduce((a, b) => a + b, 0);
console.log(sum);
You can flatten the array, filter-out single-instance values, and sum the result:
const data = [
[ 1, 7, 3, 8 ],
[ 3, 2, 9, 4 ],
[ 4, 3, 2, 1 ]
];
const numbers = new Set( data.flat(Infinity).filter(
(value, index, arr) => arr.lastIndexOf(value) != index)
);
const sum = [ ...numbers ].reduce((a, b) => a + b, 0);
Another approach could be the check the first and last index of the number in a flattened array, deciding whether or not it ought to be added to the overall sum:
let sum = 0;
const numbers = data.flat(Infinity);
for ( let i = 0; i < numbers.length; i++ ) {
const first = numbers.indexOf( numbers[ i ] );
const last = numbers.lastIndexOf( numbers[ i ] );
if ( i == first && i != last ) {
sum = sum + numbers[ i ];
}
}
// Sum of numbers in set
console.log( sum );
I am facing an issue where I get results from API(mainly array of numbers), but if the devs make mistake and leave the field empty I will get empty string ("").
I am trying to sort this array in an ascending order and move the empty strings in the back of the Array, like that:
let arr = [3, 4, "", 1, 5, 2] // Example Array from api
This array, when modified should become:
let res = [1, 2, 3, 4, 5, ""]
I tried using the arr.sort() method, but the results look like that:
let res = ["",1 ,2 ,3 ,4 ,5]
For some reason when the element is string, the sort method puts it in the front, not in the end like it does with undefined or null for example.
Method 1
let arr = [3, 4, "", 1, 5, 2];
const res = arr.sort((a, b) => {
if (typeof a === 'string') {
return 1;
} else if (typeof b === 'string') {
return -1;
} else {
return a - b;
}
}
);
console.log(res)
Output:
[ 1, 2, 3, 4, 5, '' ]
Method 2
const res = (arr) => {
let newArr = [];
let strArr = [];
for (let i = 0; i < arr.length; i++) {
if (typeof arr[i] === 'string') {
strArr.push(arr[i]);
} else {
newArr.push(arr[i]);
}
}
return newArr.concat(strArr);
}
console.log(res(arr));
I have written code in javascript trying to return a single sorted array by giving two sortedarray inputs.
function finalArray(arr1, arr2) {
const mergedArray = [];
if (arr1.length === 0) {
return arr2;
}
if (arr2.length === 0) {
return arr1;
}
let arr1Item = arr1[0];
let arr2Item = arr2[0];
let i = 1;
let j = 1;
while (arr1Item || arr2Item) {
if (arr2Item === undefined || arr1Item < arr2Item) {
mergedArray.push(arr1Item);
arr1Item = arr1[i];
i++;
} else {
mergedArray.push(arr2Item);
arr2Item = arr2[j];
j++;
}
}
return mergedArray
}
console.log(finalArray([2, 6, 4, 10], [15, 1, 5, 33]));
Can anyone help with how to merge unsorted arrays?
Merge your two arrays first, then perform the sort?
const arr1 = [2, 6, 4, 10];
const arr2 = [10, 1, 5, 33];
const newArray = ([...arr1, ...arr2]);
newArray.sort(function(a,b){return a - b});
console.log(newArray);
Expected output: [1, 2, 4, 5, 6, 10, 10, 33]
The problem is you are comparing every two pair of data and pushing smaller one.
First try to sort each sub array without entering compare process for mixing.
After the sub arrays are being sorted, then compare to each other.
This question already has answers here:
Remove duplicate values from JS array [duplicate]
(54 answers)
Completely removing duplicate items from an array
(11 answers)
remove all elements that occur more than once from array [duplicate]
(5 answers)
Closed 2 years ago.
I am trying to exclude duplicate numbers from the array. For example: if I filter an array of [1,2,2,3,5,5] the output should be [1,3].
function unique(arr) {
let sortArr = arr.sort()
let res = []
for (let i = 0; i < arr.length; i++) {
if (sortArr[i] != sortArr[i + 1]) {
res.push(sortArr[i])
}
}
return res
}
console.log(unique([1, 2, 2, 3, 5, 5]))
I was trying not to add duplicate numbers into an array, but instead of [1,3] I am getting [1,2,3,5]
The easiest tweak would be to check that both the next element and the previous element don't equal the current element:
function unique(arr) {
let sortArr = arr.sort()
let res = []
for (let i = 0; i < arr.length; i++) {
if (sortArr[i] != sortArr[i + 1] && sortArr[i] !== sortArr[i - 1]) {
res.push(sortArr[i])
}
}
return res
}
console.log(unique([1, 2, 2, 3, 5, 5]))
But .sort has a computational complexity of O(n log n). This can be done in O(n) time by counting up the number of results in an object instead:
function unique(arr) {
const ones = new Set();
const dupes = new Set();
for (const item of arr) {
if (dupes.has(item)) continue;
if (ones.has(item)) {
dupes.add(item);
ones.delete(item);
} else ones.add(item);
}
return [...ones];
}
console.log(unique([1, 2, 2, 3, 5, 5]))
Using Array.reduce, you can get the duplicated count of each item and based on that data, can get the non-duplicated values only as follows.
function unique(arr) {
const groupBy = arr.reduce((acc, cur) => {
acc[cur] ? acc[cur] ++ : acc[cur] = 1;
return acc;
}, {});
return Object.entries(groupBy)
.filter(([key, value]) => value === 1)
.map(([key]) => +key);
}
console.log(unique([1, 2, 2, 3, 5, 5]));
Count the number of values and returns only those that are equal to 1
function unique(array) {
var map = new Map();
array.forEach(a => map.set(a, (map.get(a) || 0) + 1));
return array.filter(a => map.get(a) === 1);
}
console.log(unique([1, 2, 2, 3, 5, 5]));
This question already has answers here:
How to get the difference between two arrays in JavaScript?
(84 answers)
Closed 2 years ago.
I wrote the function to accomplish what was asked, but was wondering if there was a better and nicer way to do that?
function arrayDiff(a, b) {
let myArr = [];
for (let i = 0; i < a.length; i++) {
if (a[i] == b[0] || a[i] == b[1]) {
continue;
} else {
myArr.push(a[i]);
}
}
return myArr;
}
arrayDiff([1,2,3], [2,3]) //returns [1]
What if the length of the array "b" was more than just two elements, for example 5, how could I write a better code?
You could take a single comparison by using Array#includes.
function arrayDiff(a, b) {
let myArr = [];
for (let i = 0; i < a.length; i++) {
if (b.includes(a[i])) continue;
myArr.push(a[i]);
}
return myArr;
}
console.log(arrayDiff([1, 2, 3], [2, 3])); // [1]
Another faster approach takes an object with O(1) fo looking for the value of b, for example with a Set.
function arrayDiff(a, b) {
let myArr = [],
excluding = new Set(b);
for (let i = 0; i < a.length; i++) {
if (excluding.has(a[i])) continue;
myArr.push(a[i]);
}
return myArr;
}
console.log(arrayDiff([1, 2, 3], [2, 3])); // [1]
const a = [1,2,3], b = [2,3]
let result = a.filter(n=>!b.includes(n))
console.log(result)
You can loop the second array and get the index of the item from the first array. Then use splice to remove the item from first array
function arrayDiff(a, b) {
let z = a;
b.forEach((item) => {
const getIndx = z.indexOf(item);
if (getIndx !== -1) {
z.splice(getIndx, 1)
}
});
return z;
}
console.log(arrayDiff([1, 2, 3], [2, 3]))