I am trying to solve a problem and I have having a hard time getting the answer from my splice method. I am trying to pull out all the odd numbers from an array, put them in order, and place them back in the array while leaving the even numbers in place. In my last for loop I am attempting to use splice to get the index of the current odd number, remove it, and put the sorted odd number back in with via a variable. It's not going the way I intended. Thanks for any help I can get.
function sortArray(array) {
var odds = [];
for (var i = 0; i < array.length; i++) {
if (array[i] % 2 !== 0) {
odds.push(array[i]);
}
}
odds.sort();
console.log('array', array)
for (var j = 0; j < array.length; j++) {
var x = 0;
if (array[i] % 2 !== 0) {
x = odds.shift();
console.log('x', x)
array.splice(i, 1, x); <-- I think this is my problem...maybe...
console.log('array 2', array)
}
}
console.log(array)
return array;
}
sortArray([5, 3, 2, 8, 1, 4])
These are the console logs I am getting from it:
array [ 5, 3, 2, 8, 1, 4 ]
x 1
array 2 [ 5, 3, 2, 8, 1, 4, 1 ]
x 3
array 2 [ 5, 3, 2, 8, 1, 4, 3 ]
x 5
array 2 [ 5, 3, 2, 8, 1, 4, 5 ]
x undefined
array 2 [ 5, 3, 2, 8, 1, 4, undefined ]
x undefined
array 2 [ 5, 3, 2, 8, 1, 4, undefined ]
x undefined
array 2 [ 5, 3, 2, 8, 1, 4, undefined ]
x undefined
array 2 [ 5, 3, 2, 8, 1, 4, undefined ]
[ 5, 3, 2, 8, 1, 4, undefined ]
=> [ 5, 3, 2, 8, 1, 4, undefined ]
splice expect two arguments
Index of element from where you want to start deletion.
Number of items to be deleted.
so in your code.
Step-1 : create Odd number array
Step-2 : sort it
Step-3 : remove odd number from existing array
step-4 : concat odd number array to the end of existing array.
Step-1 & 2 are fine
for step -3 & 4
for (var j = 0; j < array.length; j++) {
var x = 0;
if (array[j] % 2 !== 0) {
array.splice(j, 1);
}
}
array = array.concat(odds);
Related
So, as an input I have two arrays, A and B. Let's suppose that these are the values inside the two:
A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and B = [1, 3, 5, 7, 9]
After the deletion the array A should be [2, 4, 6, 8, 10].
I have written (Javascript) this functioning algorithm to solve this problem:
for (var i=0; i < A.length; i++) {
for (var j=0; j < B.length; j++) {
if(B[j] == A[i])
A.splice(i, 1) // Removes 1 element of the array starting from position i
}
}
I would like to know, is it possible to solve this problem without using a double loop?
What about this:
let A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ;
const B = [1, 3, 5, 7, 9];
A = A.filter(num => !B.includes(num));
Yes it is. You could use a Set. In terms of Set operations you are computing the difference A \ B.
Using a set which is optimized for lookups in O(1) time will speed up the computing the difference siginificantly from O(n²) when using includes() or double for loop to O(n).
const A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const B = [1, 3, 5, 7, 9]
const setB = new Set(B);
const difference = A.filter(x => !setB.has(x));
console.log(difference);
Maybe that ?
const
A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
, B = [1, 2, 3, 5, 7, 9] // no gaps in 1,2 and 2,3
;
for (let i =0, j=0 ; i < A.length; i++)
{
if (A[i]===B[j]) { A.splice(i--,1); j++ }
}
document.write( JSON.stringify(A) )
or (faster code)
const
A = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
, B = [ 1, 3, 5, 7, 9 ]
;
for (let i = A.length, j= B.length -1 ; i-- ; )
{
if (A[i]===B[j]) { A.splice(i,1); j-- }
}
document.write( JSON.stringify(A) )
I am learning JS, and I have homework. I am asked to transform array into new array where each item is represented by the running count of element appearances.
For example
[1, 2, 1, 1, 3]
becomes
[1, 1, 2, 3, 1]
I wrote a code which works for numbers, but fails tests with strings:
UPDATE: IT works for some numbers, for others does not :/
function duplicates(arr) {
let i, j, newArr = [],
count = 1;
for (i = 0; i < arr.length; i++) {
for (j = 0; j < arr.length; j++) {
if (i == j) {
continue
}
if (arr[i] === arr[j]) {
newArr.push(count++)
break
}
}
if (j === arr.length) {
newArr.push(1)
}
}
return newArr
}
console.log(duplicates(['a', 'a', 'aa', 'a', 'aa'])) //[ 1, 2, 1, 3, 2] <-- FAILS
console.log(duplicates([1, 2, 1, 2, 3, 1])) //[1, 2, 3, 4, 1, 5] <-- fails
console.log(duplicates([1, 2, 1, 1, 3])) //[ 1, 1, 2, 3, 2, 1 ] <-- MY CODE WORKS
Can you give me a hint? :/
Thank you!
One approach is to use .map(), .slice() and .filter()
const duplicates = (nums) =>
nums.map((value, index) => {
const segment = nums.slice(0,index+1);
return segment.filter(v => v === value).length;
});
console.log(duplicates([1, 2, 1, 1, 3]));
console.log(duplicates([1, 2, 1, 2, 3, 1]));
console.log(duplicates(['a', 'a', 'aa', 'a', 'aa']));
map creates a new array by iterating through nums and transforming each value via a function
slice is used to create a new array based on nums. In first example, the new array is [1] in first iteration, [1,2] in second, followed by [1,2,1] and so on.
filter finds the items in the array from #2 that match the current value.
Elaborating on #CRice and #Kaiido idea, let's create an object that is creating the count of the items while you're looping through the array:
function duplicates(arr) {
const obj = {};
let value = 0;
let newArr = [];
for (i = 0; i < arr.length; i++) {
value = arr[i];
if (obj[value]){
obj[value] = obj[value] + 1;
}
else{
obj[value] = 1;
}
newArr.push(obj[value]);
}
return newArr
}
console.log(duplicates(['a', 'a', 'aa', 'a', 'aa'])) //[ 1, 2, 1, 3, 2] <-- FAILS
console.log(duplicates([1, 2, 1, 2, 3, 1])) //[1, 2, 3, 4, 1, 5] <-- fails
console.log(duplicates([1, 2, 1, 1, 3])) //[ 1, 1, 2, 3, 2, 1 ] <-- MY CODE WORKS
JS has a nice built-in, reduce, that does so in a simpler way:
const duplicates = (arr) => {
const obj = {}
return arr.reduce ( (acc,cur) => {
obj[cur] = (obj[cur])?obj[cur]+1:1
acc.push(obj[cur])
return acc
}, []);
}
console.log(duplicates(['a', 'a', 'aa', 'a', 'aa'])) //[ 1, 2, 1, 3, 2] <-- FAILS
console.log(duplicates([1, 2, 1, 2, 3, 1])) //[1, 2, 3, 4, 1, 5] <-- fails
console.log(duplicates([1, 2, 1, 1, 3])) //[ 1, 1, 2, 3, 2, 1 ] <-- MY CODE WORKS
I have an array like so: [1, 2, 3, 4, 5, 6, 7, 9, 10]. I need to chunk it into different size chunks, yet with a simple pattern of: 4, 3, 3, 3, 4, 3, 3, 3 like so:
[
[ // four
1,
2,
3,
4
],
[ // three (1/3)
5,
6,
7
],
[ // three (2/3)
8,
9,
10
],
[ // three (3/3)
11,
12,
13
],
[ // four
14,
15,
16,
17
],
[ // three (1/3)
18,
19,
20
], // and so on..
]
I have tried with this code I have customized:
const arr; // my array of values
const chuncked = arr.reduce((acc, product, i) => {
if (i % 3) {
return acc;
} else if (!didFourWayReduce) {
didFourWayReduce = true;
fourWayReduces++;
if ((fourWayReduces - 1) % 2) { // only make every second a "4 row"
return [...acc, arr.slice(i, i + 3)];
} else {
return [...acc, arr.slice(i, i + 4)];
}
} else {
didFourWayReduce = false;
return [...acc, arr.slice(i, i + 3)];
}
}, []);
And it works, almost, expect that the first chunk of threes (1/3) have the last element of the chunk with 4. So 1 key is repeated every first chunk of three. Like so:
[
[
1,
2,
3,
4
],
[
4, // this one is repeated, and it shouldn't be
5,
6
]
]
You could take two indices, one for the data array and one for sizes. Then slice the array with a given length and push the chunk to the chunks array.
Proceed until end of data.
var data = Array.from({ length: 26 }, (_, i) => i + 1),
sizes = [4, 3, 3, 3],
i = 0,
j = 0,
chunks = [];
while (i < data.length) chunks.push(data.slice(i, i += sizes[j++ % sizes.length]));
console.log(chunks);
.as-console-wrapper { max-height: 100% !important; top: 0; }
const arr = Array.from({ length: 100 }, (_, i) => i);
const copy = [...arr];
const sizes = [4, 3, 3, 3];
const result = [];
let i = 0;
while (i <= arr.length && copy.length) {
result.push(copy.splice(0, sizes[i % sizes.length]));
i++;
}
console.log(result);
A recursive approach is fairly elegant:
const chunks = (xs, [s, ...ss]) =>
xs.length ? [xs .slice (0, s), ... chunks (xs .slice (s), [...ss, s])] : []
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
const sizes = [4, 3, 3, 3]
console .log (chunks (data, sizes))
.as-console-wrapper { max-height: 100% !important; top: 0; }
By replacing [s, ...ss] with [...ss, s], we pass a cycled version of the sizes array, so that for instance, [4, 3, 3, 3] becomes [3, 3, 3, 4]. This makes it easy to parse step-by-step.
Mod operator to check if it should be 4 or 3. Use two arrays just to make it easier (can be done with one)
const groupIt = arr => arr.reduce(({
group,
out
}, v, i) => {
var max = out.length % 4 === 0 ? 4 : 3
group.push(v)
if (group.length === max || i === arr.length - 1) {
out.push(group)
group = []
}
return {
group,
out
}
}, {
group: [],
out: []
}).out
console.log(groupIt([1, 2, 3, 4, 5, 6, 7, 8]))
var test = (new Array(30)).fill(0).map((x,i) => i + 1)
console.log(groupIt(test))
with just one:
const groupIt = arr => arr.reduce((out, v, i) => {
var max = (out.length - 1) % 4 === 0 ? 4 : 3
out[out.length - 1].push(v)
if (out[out.length - 1].length === max) {
out.push([])
}
return out
}, [[]])
console.log(groupIt([1, 2, 3, 4, 5, 6, 7, 8]))
var test = (new Array(30)).fill(0).map((x, i) => i + 1)
console.log(groupIt(test))
This answer is similar to that of Nina Scholz, but uses a for loop, which I personally find more clear.
const arr = Array.from({length: 100}, (_, i) => i + 1);
const sizes = [4, 3, 3, 3];
const result = [];
for (let i = 0, j = 0; i < arr.length; i += sizes[j], j = (j + 1) % sizes.length) {
result.push(arr.slice(i, i + sizes[j]));
}
console.log(result);
example value return:
array[1]=1
array[5]=5
array[12]=[1, 2]
array[85]=[8, 5]
array[7453]=[7, 4, 5, 3]
array[8987556322415]=[8, 9, 8, 7, 5, 5, 6, 3, 2, 2, 4, 1, 5]
Which is the best way to convert the index to an array with single decimal value (only one number for every index)
var array=[30];
function getVal(array){
for ( i=0; i<i.length; i++ ){
....
} return array;
}
getVal(array);
-> array [1] = 0
-> array [0] = 3
Cast it to string, and since string is an array of char, you can manullay parse them back to numbers.
var index = 8987556322415;
var arr = index.toString().split("").map(char=>parseInt(char));
console.log(arr)//[8, 9, 8, 7, 5, 5, 6, 3, 2, 2, 4, 1, 5]
Here is a JSBin for you
Items in an array can be arranged in ascending order using sort() method in JavaScript but how to arrange them in all possible ways and show them in our web page.
You describe permutations, one way to implement it:
function permutations(arr, r=[]) {
if (arr.length === 0) {
console.log(r)
} else {
const first = arr[0]
for (let i = 0; i <= r.length; i++) {
permutations(arr.slice(1), r.slice(0, i).concat([first]).concat(r.slice(i)))
}
}
}
permutations([1, 2, 3])
OUTPUT
[ 3, 2, 1 ]
[ 2, 3, 1 ]
[ 2, 1, 3 ]
[ 3, 1, 2 ]
[ 1, 3, 2 ]
[ 1, 2, 3 ]