Selectively interleave two arrays - javascript

I would like to interleave two arrays, BUT only return pairs when a certain condition is met. As an example:
first_array = [1, 2, 3, 4, 5, 6, 7, 8];
second_array = [, , , , 1, , 0, 1];
I need to return ONLY pairs where array-2 is non-null, in other words, the output I need is:
interleaved = [5, 1, 7, 0, 8, 1];
I have an interleave function that works:
function send_values() {
let interleaved = [];
for (let i = 0; i < first_array.length; i++) {
interleaved.push(first_array[i], second_array[i]);
}
}
...but the output is, obviously:
interleaved = [1, , 2, , 3, , 4, , 5, 1, 6, , 7, 0, 8, 1];
...which is not what I need. Suggestions?

You could iterate the sparse array and take only the values with the values at the same index from array one.
var array1 = [1, 2, 3, 4, 5, 6, 7, 8],
array2 = [, , , , 1, , 0, 1],
result = array2.reduce((r, v, i) => r.concat(array1[i], v), []);
console.log(result);

Here's a generic functional solution:
pairs = (a, b) => a.map((_, i) => [a[i], b[i]])
flat = a => [].concat(...a)
valid = x => x === 0 || Boolean(x)
array_1 = [1, 2, 3, 4, 5, 6, 7, 8];
array_2 = [ , , , , 1, , 0, 1];
result = flat(
pairs(array_1, array_2)
.filter(x => x.every(valid))
)
console.log(result)
Works both ways, that is, it doesn't matter which array contains the null values. Also, you can redefine valid if there are other things to exclude.
As a bonus, if you replace pairs with zip, you can make it work for any number of arrays.

Related

How to triplicate specific items in an array for javascript?

Is there any way to only triplicate certain elements in an array? I want to triplicate the "3" in the array only.
For instance:
const deck = [1, 3, 9, 3, 7];
should become [1, 3, 3, 3, 9, 3, 3, 3, 7]
I have tried the method below, deck is the random array:
var i;
for (let i=0;i<deck.length;i++){
if (deck[i]==3){
return deck.flatMap(x=>[x,x,x]);
}else return deck[i];
}
}
You could write a function that uses flatMap() to map over the array and triplicate the specific values.
const deck = [1, 3, 9, 3, 7];
const triplicate = (number, arr) => {
return arr.flatMap(x => x === number ? [x, x, x]: x);
}
console.log(triplicate(3, deck));
Using Array#flatMap:
const triplicate = (arr = [], number) =>
arr.flatMap(n => n === number ? [n, n, n] : n);
console.log( triplicate([1, 3, 9, 3, 7], 3) );

Relative Sort Array Javascript

I am working on a problem on LeetCode and having some troubles
https://leetcode.com/problems/relative-sort-array/
Instructions:
Given two arrays arr1 and arr2, the elements of arr2 are distinct, and all elements in arr2 are also in arr1.
Sort the elements of arr1 such that the relative ordering of items in arr1 are the same as in arr2. Elements that don't appear in arr2 should be placed at the end of arr1 in ascending order.
Example 1:
Input: arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
Output: [2,2,2,1,4,3,3,9,6,7,19]
my attempt:
var relativeSortArray = function(arr1, arr2) {
let arr =[]
let end =[]
for (i=0; i<arr2.length; i++){
for (j=0; j<arr1.length; j++){
if(arr2[i] == arr1[j]){
arr.push(arr1[j])
}else{
end.push(arr1[j])
}
}
}
end.sort((a,b) => a-b)
console.log(end)
return arr
};
The If conditional works but the else condition isn't and I can't figure out why.
I think console.log(end) should give me the two numbers not in arr2 but it instead gives me:
[
1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 6,
6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 9, 9,
9, 9, 9, 19, 19, 19, 19, 19, 19
]
Why is this happening?
Thanks!!!
You could take an object for the position of a value and take a large value like Number.MAX_VALUE as default value. If the delta is zero sort by value.
Taking a delta is a standard by using Array#sort. This returns a value smaller than zero, zero or greater than zero, depending on the values. The sort method receives this values and keeps or swaps the values.
const
relativeSort = (array, given) => {
const order = Object.fromEntries(given.map((v, i) => [v, i + 1]));
return array.sort((a, b) =>
(order[a] || Number.MAX_VALUE) - (order[b] || Number.MAX_VALUE) ||
a - b
);
};
console.log(...relativeSort([2, 3, 1, 3, 2, 4, 6, 7, 9, 2, 19], [2, 1, 4, 3, 9, 6]));
In each iteration of arr2:
all the numbers that are different from the current number are pushed to the end array
For example,
First iteration - compare number (2) and you will end up with:
arr: [2,2,2]
end: [3,1,3,4,6,7,9,19]
Second iteration - compare number (1) and you will end up with:
arr: [2,2,2,1]
end: [3,1,3,4,6,7,9,19] + [2,3,3,2,4,6,7,9,2,19]
try to debug your code to follow the flow
class Solution:
def relativeSortArray(self, arr1: list[int], arr2: list[int]) -> list[int]:
arr = []
for i in arr2:
value = arr1.count(i)
for j in range(value):
arr.append(i)
arr1.remove(i)
arr1.sort()
return arr+arr1
obj = Solution()
arr1 = [28,6,22,8,44,17]
arr2 = [22,28,8,6]
result = obj.relativeSortArray(arr1,arr2)
print(result)

JavaScript move along all items in array by X number

I'm wanting to create a function which accepts 2 arguments, first argument is an array, second argument is a number of index positions to move all the array items.
So for example if I passed exampleFunc([1,2,3,4,5], 2) it should move all items 2 places to the right, so returns [4,5,1,2,3]. I've done the following, however is there a more eloquent / efficient way of doing this? Also if I wanted to reverse the direction and condense into 1 function and not two as done below, any suggestions how to do this other than putting conditionals around the different part of each function? Tried using .splice() method but didn't really got anywhere. Any help would really be appreciated!
const moveArrayPositionRight = (array, movePositions) => {
let newArray = new Array(array.length);
for (i = 0; i < array.length; i++) {
let newIndex = i - movePositions;
if (newIndex < 0) {
newIndex += array.length;
}
newArray[i] = array[newIndex];
}
return newArray;
};
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 2)); // output: [8, 10, 2, 4, 6]
const moveArrayPositionLeft = (array, movePositions) => {
let newArray = new Array(array.length);
for (i = 0; i < array.length; i++) {
let newIndex = i - movePositions;
if (newIndex < 0) {
newIndex += array.length - 1;
}
newArray[i] = array[newIndex];
}
return newArray;
};
console.log(moveArrayPositionLeft([3, 6, 9, 12, 15], 2)); // output: [9,12,15,3,6]
You have the index of the position where you want to slice the array up and rearrange it, so you can use .slice to do exactly that - extract the sub-arrays that need to be rearranged, and put into a new array:
const moveArrayPositionRight = (array, movePositions) => [
...array.slice(array.length - movePositions),
...array.slice(0, array.length - movePositions)
];
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 2)); // output: [8, 10, 2, 4, 6]
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 3)); // expected [6, 8, 10, 2, 4]
.slice can also take negative indicies to slice an amount from the end instead of from the beginning:
const moveArrayPositionRight = (array, movePositions) => [
...array.slice(-movePositions),
...array.slice(0, -movePositions)
];
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 2)); // output: [8, 10, 2, 4, 6]
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 3)); // expected [6, 8, 10, 2, 4]
Can also use .concat instead of spread
const moveArrayPositionRight = (array, movePositions) => array
.slice(array.length - movePositions)
.concat(array.slice(0, array.length - movePositions));
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 2)); // output: [8, 10, 2, 4, 6]
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 3)); // expected [6, 8, 10, 2, 4]
Same sort of thing for moveArrayPositionLeft:
const moveArrayPositionLeft = (array, movePositions) => [
...array.slice(movePositions),
...array.slice(0, movePositions)
];
console.log(moveArrayPositionLeft([3, 6, 9, 12, 15], 2)); // output: [9,12,15,3,6]

Reorder with recursive function

How to use recursive function to reordered array with even indices first and then odd indices?
For example:
input: [5, 2, 4, 9]
output: [5, 4, 2, 9]
I want to improve this code.
let arrayB = [],
arrayOdd = [],
arrayEven = [];
let i = 0;
const reorder = (arrayA) => {
if (arrayA.length >= 2) {
if (i < arrayA.length) {
i === 0 || i % 2 === 0 ? arrayEven.push(arrayA[i]) : arrayOdd.push(arrayA[i]);
i++;
arrayB = [...arrayEven, ...arrayOdd];
reorder(arrayA);
} else {
arrayOdd = [];
arrayEven = [];
i = 0;
}
return arrayB;
}
}
console.log(reorder([4, 8, 12, 16]));
console.log(reorder([1, 2, 3, 4, 5, 6, 7, 8, 9]));
No idea why you'd need a recursive function. This should do it:
const reorder = (a) => [...a.filter((_, i) => !(i % 2)), ...a.filter((_, i) => i % 2)];
console.log(reorder([4, 8, 12, 16]));
console.log(reorder([1, 2, 3, 4, 5, 6, 7, 8, 9]));
Because you stipulate your in comments that you have instructions to use a recursive function with minimum space requirements, here's a solution that uses Array.prototype.splice() to modify the array in place:
const reorder = (a, offset = 2) => {
if (offset < a.length) {
a.splice(offset / 2, 0, ...a.splice(offset, 1));
return reorder(a, offset + 2);
}
return a;
};
console.log(reorder([4, 8, 12, 16]));
console.log(reorder([1, 2, 3, 4, 5, 6, 7, 8, 9]));
Note that, like the Array.prototype.sort() function, the above function only returns the array for convenience. No new array is created.
I think you can do this by using sort method of array. but for that you might need to use map to get index and then converting back to values.
const isOdd = n => n % 2 === 1;
const reorder = input => input.map((value, index) => ({index, value})).sort((a,b) =>
isOdd(a.index) ? 1 : isOdd(b.index) ? -1 : 0).map(({value}) => value);
console.log(reorder([4, 8, 12, 16]));
console.log(reorder([1, 2, 3, 4, 5, 6, 7, 8, 9]));
Avoid using global variables.
const reorder = (arrayA, arrayOdd = [], arrayEven = []) => {
if (arrayA.length >= 1)
arrayEven.push(arrayA.shift());
if (arrayA.length >= 1) {
arrayOdd.push(arrayA.shift());
reorder(arrayA, arrayOdd, arrayEven);
}
return [...arrayEven, ...arrayOdd];
}
console.log(reorder([4, 8, 12, 16]));
console.log(reorder([1, 2, 3, 4, 5, 6, 7, 8, 9]));
I don't know why you would choose to do this recursively, but this seems to do it:
const evenThenOdd = ([e = undefined, o = undefined, ...xs], evens = [], odds = []) =>
e == undefined
? [...evens, ...odds]
: o == undefined
? evenThenOdd ( xs, [...evens, e] [odds] )
: evenThenOdd ( xs, [...evens, e], [...odds, o] )
console .log (
evenThenOdd ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
//~> [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
)
We keep evens and odds arrays of values. The base case, when there is nothing left in the array, is to just concatenate those two arrays. The other two cases are when there is one item left and where there are two or more items left. If the undefined values are legitimate elements of your array you want to handle, then add const None = Symbol(), and replace each undefined with None.
A cleaner, non-recursive solution might look like this:
const evenThenOdd = (xs) => [
...xs.filter((_, i) => i % 2 == 0),
...xs.filter((_, i) => i % 2 == 1),
]

Javascript - Put array items, including their duplicates, into a new array

I couldn't find an answer to this specific question on S.O.
Let's say I have an array of strings, or in this case, numbers:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
I'd like the output to be:
var output = [[1,1,1], [2], [3,3,3,3,3], [4], [5, 5, 5]];
I was hoping to use Lodash but most of that stuff tends to remove duplicates rather chunk them together into their own array. Maybe some kind of .map iterator?
The order of the output doesn't really matter so much. It just needs to chunk the duplicates into separate arrays that I'd like to keep.
You can use reduce to group the array elements into an object. Use Object.values to convert the object into an array.
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
var result = Object.values(x.reduce((c, v) => {
(c[v] = c[v] || []).push(v);
return c;
}, {}));
console.log(result);
Shorter version:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
var result = Object.values(x.reduce((c, v) => ((c[v] = c[v] || []).push(v), c), {}));
console.log(result);
You can do this with Array.reduce in a concise way like this:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5]
let result = x.reduce((r,c) => (r[c] = [...(r[c] || []), c],r), {})
console.log(Object.values(result))
The exact same with lodash would be:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5]
let result = _.values(_.groupBy(x))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Using _.values to extract the values of the grouping object and _.groupBy to get the actual groupings
Use Array#prototype#reduce to group them:
const x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
let helperObj = {};
const res = x.reduce((acc, curr) => {
// If key is not present then add it
if (!helperObj[curr]) {
helperObj[curr] = curr;
acc.push([curr]);
}
// Else find the index and push it
else {
let index = acc.findIndex(x => x[0] === curr);
if (index !== -1) {
acc[index].push(curr);
}
}
return acc;
}, []);
console.log(res);
Since you're hoping to use Lodash, you might be interested in groupBy. It returns on object, but the _.values will give you the nested array:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
let groups = _.values(_.groupBy(x))
console.log(groups)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Here's an imperative solution:
var x = [1, 1, 1, 2, 3, 3, 5, 3, 3, 5, 4, 5];
x.sort();
var res = [];
for (const [i, n] of x.entries()) {
if (n !== x[i-1]) res.push([n]);
else res[res.length-1].push(n);
}
console.log(res);

Categories