This question already has answers here:
Javascript unlimited nested array handling
(6 answers)
Closed 8 years ago.
I found this code on http://games.usvsth3m.com/javascript-under-pressure/ and I reach the 5th problem which requires to estimate the sum of all the integer in the list. The list may contains nested lists. So for a list [1,2,3,4,5] or [[1,2,3],4,5] the code below works but for a list [[[[[1]]]],2,3,4] does not. I try a lot of hours and I do not know to solve it. I need a hit plz.
function arraySum(i) {
var sum =0;
for (var id =0; id<i.length;id++){
if(typeof i[id]==='object'){
var ar = i[id];
for (var dd =0; dd<ar.length;dd++ ){
if(typeof ar[dd]==='number'){
sum+=parseInt(ar[dd]);
}
}
}
else
if(typeof i[id]==='number'){
sum+=parseInt(i[id]);
}
}
return sum;
}
use recursion.
var arr = [1, 2, [3, 4, [[[5]]]]];
num = 0;
function loop (arr) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] instanceof Array) {
loop(arr[i]);
} else {
num += parseInt(arr[i]);
}
}
}
loop(arr);
console.log(num);
fiddle - http://jsfiddle.net/9j1hcx4x/
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I've been doing a lot of the practise tests on codility and though all my solutions work, they always have hidden stress tests which include massive arrays, the following code for example needs to take array A and find the lowest positive number missing from the sequence.
e.g: given A = [1, 3, 6, 4, 1, 2], the function should return 5. 5 is the value of i which increments in the loop. Function returns whenever index i is not found in array.
It works correctly but codility tested it with a 1-100,000 array and it timed out at the 6 second limit. most of my codes on the practise tests tend to fail for the same reason. Any help greatly appreciated.
console.log(solution([1, 3, 6, 4, 1, 2]));
function solution(A) {
let i = 0
for (i = 1; i <= A.length ; i++){
if(A.includes(i) == false){
return i
}
}
return i
}
There is no way to look through N items in less than O(n) which is what you're doing. The issue is you're looking through the array N times as well - this means you run N*N times and can be improved.
The most "typical" way to improve this approach is to use a Set or similar data structure with amortised (usually) constant-time access to elements. In your case this would look like:
console.log(solution([1, 3, 6, 4, 1, 2]))
function solution(A) {
// build existing elements, in O(N)
const values = new Set(A)
let i = 0
for (i = 1; i <= A.length; i++){
if(!values.has(i)){
return i
}
}
return i
}
This runs in O(N) (creating the set) + O(N) iterating the array and performing constant time work each time.
Your code loops through every item in the array for every item in the array. This gives a worst-case runtime of O(n^2). You can get a much better result if you sort the array, and then iterate through it looking for any missing numbers.
function compareNumeric(a,b) {
return a - b;
}
function solution(A) {
A.sort(compareNumeric);
let expect = 0;
for( let i=0; i<A.length; i++) {
if( A[i] > expect+1) return expect+1;
if( A[i] === expect+1) expect++;
}
return expect+1;
}
console.time('simple');
console.log(solution([1, 3, 6, 4, 1, 2]));
console.timeEnd('simple');
// worst-case: all numbers from 1-1M exist but are randomly shuffled in the array
const bigArray = Array.from({length:1000000},(_,i)=>i+1);
function shuffle(a) {
// credit: https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
shuffle(bigArray);
console.time('worst-case');
console.log(solution(bigArray));
console.timeEnd('worst-case');
This will give you a runtime of O(n log n) and should be the fastest possible solution as far as I can tell.
Please check the two solutions, it will take the time complexity O(n * log n) or O(n) so it will be much faster than previous work.
const arrayGenerator = (len) => {
const array = [];
for(let i = 0; i < len; i ++) {
array.push(Math.floor(Math.random() * len) + 1);
}
return array;
}
function sort_array_solution(A) {
A.map(a=>a).sort((a, b)=>a - b)
let ans = 1;
for(let i = 0; i < A.length; i ++) {
if(A[i] < ans) continue;
if(A[i] > ans) return ans;
ans ++;
}
return ans;
}
function object_key_solution(A) {
const obj = {}
for(let i = 0; i < A.length; i ++) {
obj[A[i]] = 1;
}
for(let ans = 1; ; ans ++) {
if(!obj.hasOwnProperty(ans)) return ans;
ans ++;
}
return ans;
}
console.log(sort_array_solution([1,2]))
console.log(object_key_solution([1,2]))
const arr = arrayGenerator(10);
console.log(sort_array_solution(arr))
console.log(object_key_solution(arr))
const arr1 = arrayGenerator(100000);
console.log(sort_array_solution(arr1))
console.log(object_key_solution(arr1))
This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
How to convert a string to an integer in JavaScript
(32 answers)
Closed 1 year ago.
function removeDups(arr) {
let x = {};
for (let i=0; i<arr.length; i++) {
if(!x[arr[i]]) {
x[arr[i]] = true;
}
}
let result = Object.keys(x);
for(let i=0; i<result.length; i++) {
if(typeof result[i] == Number) {
result[i] = parseInt(result[i]);
}
}
return result;
}
removeDups([1, 0, 1, 0]);
//➞ [1, 0]
Hey guys trying to return [1,0] like the problem states but I keep returning ['1','0']. I'm trying to convert these values to numbers and not having much luck. Any help?
This question already has answers here:
When looping through values of a JS array, and I remove value, do I need to use while instead of for?
(5 answers)
Closed 1 year ago.
I am trying to make a function that removes the duplicate array elements from an array and returns the same array with no duplicates. I figured this would work:
var removeDuplicates = function(nums) {
nums.sort(function(a,b){ return a-b;});
let len = nums.length;
for (let i = 0; i < nums.length; i++){
if (nums[i] === nums[i+1]){
nums.splice(i,1);
}
}
return nums;
};
console.log(removeDuplicates([0,0,1,1,1,2,2,3,3,4]));
However the console log at the bottom returns nums as [0,1,1,2,3,4] and not the [0,1,2,3,4] I was expecting. Is there any way to modify the for loop or use splice differently (or maybe some other array method that does not return a new array) to remove that last 1 duplicate?
You need to decrement the index because the element above it will be shifted into the current index.
var removeDuplicates = function(nums) {
nums.sort(function(a,b){ return a-b;});
let len = nums.length;
for (let i = 0; i < nums.length; i++){
if (nums[i] === nums[i+1]){
nums.splice(i,1);
--i;
}
}
return nums;
};
console.log(removeDuplicates([0,0,1,1,1,2,2,3,3,4]));
Alternatively, looping backwards avoids this issue altogether.
var removeDuplicates = function(nums) {
nums.sort(function(a,b){ return a-b;});
let len = nums.length;
for (let i = nums.length - 1; i >= 0; i--){
if (nums[i] === nums[i+1]){
nums.splice(i,1);
}
}
return nums;
};
console.log(removeDuplicates([0,0,1,1,1,2,2,3,3,4]));
A simpler method would be to use a Set.
var removeDuplicates = function(nums) {
return [...new Set(nums.sort((a,b)=>a-b))];
};
console.log(removeDuplicates([0,0,1,1,1,2,2,3,3,4]));
This question already has answers here:
Looping through array and removing items, without breaking for loop
(17 answers)
Closed 3 years ago.
Here is the question
Q) take 2 arrays and pass it to a function, then check if the square of the array1 is contained in the array2 (Note: Order doesn't matter, also 2 duplicates in arr1[1,2,2], there should be 2 duplicates in arr2[1,4,4]).
I have this code in which, i am trying to convert the indexOf to a for loop and i have included that code which i tried after this code
function same2(arr1, arr2){
if (arr1.length !== arr2.length){
return false;
}
for (let i = 0; i < arr1.length; i++){
let currentIndex = arr2.indexOf(arr1[i] ** 2);
// if the square of arr1 is contained in any of the index in arr2
if (currentIndex === -1){
return false;
}
console.log(arr2);
arr2.splice(currentIndex, 1);
}
return true;
}
same2([10,2, 3, 5], [100, 4, 25, 9]);
Here is the code with 2 for loop and its giving wrong output for the corresponding input.
function same(arr1, arr2){
if (arr1.length !== arr2.length){
return false;
}
for (let i = 0; i < arr1.length; i++){
for (let j = 0; j < arr2.length; j++){
let currentIndex = arr1[i] ** 2;
console.log(currentIndex);
if (currentIndex === -1){
return false;
}
if (arr2[j] === currentIndex){
arr2.splice(currentIndex, 1);
// console.log(arr2);
}
}
}
return true;
}
same([1, 10,2, 4], [10, 1, 16, 4]);
I know i have problem with the index of the array, but i am not able to break it.
What about this functional approach?
test2 = (i1, i2) => i1.length === i2.length && i1.reduce((a,c) => a && i2.includes(c*c), 1)
console.log(test2([1,2,3],[1,4,9]))
Update 1
Here is a double loop approach, but somehow different from yours as you have several things wrong there. First of all: with splice you are modifying the array for which you have a for loop - that is something you should never do. Secondly, you have recalculated the value you are looking for in the inner loop - that made it absolutelly unusable. You don't need that variable at all, but I have used it to be more straightforward.
Update 2
If you want to have an element in arr2 to count only once, you can introduce the trick to remove that element - without modifying the array with splice.
function same(arr1, arr2){
if (arr1.length !== arr2.length){
return false;
}
for (let i = 0; i < arr1.length; i++){
let lookFor = arr1[i] ** 2;
let found = false;
for (let j = 0; j < arr2.length; j++){
if (arr2[j] === lookFor){
delete arr2[j]
found = true
break;
}
}
if(!found) return false
}
return true;
}
console.log(same([1,2,2],[1,4,4]))
console.log(same([1,2,2],[1,1,4]))
This question already has answers here:
How to randomize (shuffle) a JavaScript array?
(69 answers)
Closed 6 years ago.
I have an array
var array = ["what","is","going","on"];
I know it's possible to access and list these elements with a standard for loop like so:
for (i = 0; i <= array.length; i++) {
console.log(array[i]);
}
But I want to know if there's a way to list these elements in a random order. I suspect that I have to use some variation of Math. but I don't have enough experience to decide which to use for sure. Thanks in advance!
You should first shuffle the array and then read one by one. An array method like Array.prototype.shuffle() might come handy.
Array.prototype.shuffle = function(){
var i = this.length,
j,
tmp;
while (i > 1) {
j = Math.floor(Math.random()*i--);
tmp = this[i];
this[i] = this[j];
this[j] = tmp;
}
return this;
};
var arr = [1,2,3,4,5].shuffle();
for(var i = 0; i < arr.length; i++) console.log(arr[i]);
Statistically speaking, this will definitely work. It just may take until the heat-death of the universe to complete.
var array = ["What", "am", "I", "doing", "with", "my", "life"];
var processed = [];
function randomAccess() {
if (processed.length === array.length) {
console.log('Done!');
return;
}
var index = Math.floor(Math.random() * array.length);
if (processed.indexOf(index) === -1) {
// Make sure we haven't processed this one before
console.log('array[' + index + ']:', array[index]);
processed.push(index);
}
// Prevent locking up the browser
setTimeout(randomAccess, 0);
}
randomAccess();
Please don't use this in production code. Theoretically, it may never complete.
Yes, you can introduce a second array to log the indices you have randomly returned - in order not to return the same index more than once.
Working example:
var myArray = ['what','is','going','on'];
var returnedIndices = [];
for (i = 0; i < myArray.length; i++) {
var randomIndex = Math.floor(Math.random() * myArray.length);
if (returnedIndices.indexOf(randomIndex) !== -1) {
i--;
continue;
}
else {
returnedIndices[i] = randomIndex;
console.log(myArray[randomIndex]);
}
}
console.log(array[Math.floor(Math.random() * (array.length - 1))]);