Combine splitted 2 string into array of object react js [duplicate] - javascript

I have 2 arrays:
var a = [1, 2, 3]
var b = [a, b, c]
What I want to get as a result is:
[[1, a], [2, b], [3, c]]
It seems simple but I just can't figure out.
I want the result to be one array with each of the elements from the two arrays zipped together.

Use the map method:
var a = [1, 2, 3]
var b = ['a', 'b', 'c']
var c = a.map(function(e, i) {
return [e, b[i]];
});
console.log(c)
DEMO

Zip Arrays of same length:
Using Array.prototype.map()
const zip = (a, b) => a.map((k, i) => [k, b[i]]);
console.log(zip([1,2,3], ["a","b","c"]));
// [[1, "a"], [2, "b"], [3, "c"]]
Zip Arrays of different length:
Using Array.from()
const zip = (a, b) => Array.from(Array(Math.max(b.length, a.length)), (_, i) => [a[i], b[i]]);
console.log( zip([1,2,3], ["a","b","c","d"]) );
// [[1, "a"], [2, "b"], [3, "c"], [undefined, "d"]]
Using Array.prototype.fill() and Array.prototype.map()
const zip = (a, b) => Array(Math.max(b.length, a.length)).fill().map((_,i) => [a[i], b[i]]);
console.log(zip([1,2,3], ["a","b","c","d"]));
// [[1, "a"], [2, "b"], [3, "c"], [undefined, "d"]]
Zip Multiple (n) Arrays:
const zip = (...arr) => Array(Math.max(...arr.map(a => a.length))).fill().map((_,i) => arr.map(a => a[i]));
console.log(zip([1,2], [3,4], [5,6])); // [[1,3,5], [2,4,6]]

Zipping by leveraging generator functions
You can also use a generator function to zip().
const a = [1, 2, 3]
const b = ['a', 'b', 'c']
/**
* Zips any number of arrays. It will always zip() the largest array returning undefined for shorter arrays.
* #param {...Array<any>} arrays
*/
function* zip(...arrays){
const maxLength = arrays.reduce((max, curIterable) => curIterable.length > max ? curIterable.length: max, 0);
for (let i = 0; i < maxLength; i++) {
yield arrays.map(array => array[i]);
}
}
// put zipped result in an array
const result = [...zip(a, b)]
// or lazy generate the values
for (const [valA, valB] of zip(a, b)) {
console.log(`${valA}: ${valB}`);
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
The above works for any number of arrays and will zip() the longest array so undefined is returned as a value for shorter arrays.
Zipping of all Iterables
Here a function which can be used for all Iterables (e.g. Maps, Sets or your custom Iterable), not just arrays.
const a = [1, 2, 3];
const b = ["a", "b", "c"];
/**
* Zips any number of iterables. It will always zip() the largest Iterable returning undefined for shorter arrays.
* #param {...Iterable<any>} iterables
*/
function* zip(...iterables) {
// get the iterator of for each iterables
const iters = [...iterables].map((iterable) => iterable[Symbol.iterator]());
let next = iters.map((iter) => iter.next().value);
// as long as any of the iterables returns something, yield a value (zip longest)
while(anyOf(next)) {
yield next;
next = iters.map((iter) => iter.next().value);
}
function anyOf(arr){
return arr.some(v => v !== undefined);
}
}
// put zipped result in aa array
const result = [...zip(a, new Set(b))];
// or lazy generate the values
for (const [valA, valB] of zip(a, new Set(b))) {
console.log(`${valA}: ${valB}`);
}
Obviously it would also be possible to just use [...Iterable] to transform any Iterable to an array and then use the first function.

Using the reduce method:
const a = [1, 2, 3]
const b = ['a', 'b', 'c']
var c = a.reduce((acc, curr, ind) => {
acc.push([curr, b[ind]]);
return acc;
}, []);
console.log(c)
With forEach method:
const a = [1, 2, 3]
const b = ['a', 'b', 'c']
const c = [];
a.forEach((el, ind) => {
c.push([el, b[ind]])
});
console.log(c)

Providing a solution with imperative programming by a simple for loop.
This performs better when doing the zip operation on huge data sets compared to the convenient array functions like map() and forEach().
Example:
const a = [1, 2, 3];
const b = ['a', 'b', 'c'];
const result = [];
for (let i = 0; i < a.length; i++) {
result.push([a[i], b[i]]);
}
console.log(result);
And if you want a 1 line simpler solution then you can use a library like ramda which has a zip function.
Example:
const a = [1, 2, 3];
const b = ['a', 'b', 'c'];
const result = R.zip(a, b);
console.log(result);

Related

Javascript check if any elements in array are equal

How should I make a function that loops through an array, and checks if any elements are equal
Example:
[a, b, c, d] //false
[a, b, a, d] //true
EDIT:
I want to use it with nested arrays, like so:
const a = [[1,2,3],[4,5,6]] //false
const b = [[1,2,3],[4,5,1]] //true
EDIT again:
I want the nested arrays to be the exact same
const a = [[1,2],[4,5]] //false
const b = [[1,2],[1,2]] //true
const c = [[1,2][3,4][1,2]] //true
You can easily do this using Set as:
const getResult = (arr) => new Set(arr).size !== arr.length;
You can add all elements to set and then compare size of set and length of arr.
You will get different length if any element is repeated else same
const arr1 = ['a', 'b', 'c', 'd']; //false
const arr2 = ['a', 'b', 'a', 'd']; //true
const getResult = (arr) => new Set(arr).size !== arr.length;
console.log(getResult(arr1));
console.log(getResult(arr2));
If you want to use nested array then you can flat it before seinding arguments to getResult function as:
const a = [
[1, 2, 3],
[4, 5, 6],
]; //false
const b = [
[1, 2, 3],
[4, 5, 1],
]; //true
const getResult = (arr) => new Set(arr).size !== arr.length;
console.log(getResult(a.flat()));
console.log(getResult(b.flat()));
Simplest way would be to loop through the array and check if the first index of the element is same as current index like this:
let a = [1, 2, 3, 4]
let b = [1, 2, 3, 1]
let isRepeated = (a) => {
for (let i = 0; i < a.length; i++) {
if (a.indexOf(a[i]) !== i)
return true;
}
return false;
}
console.log(isRepeated(a));
console.log(isRepeated(b));

Map an array to create a new array of pairs

I have two separate arrays and I'm trying to create a new nested array that has values grouped together.
Can I use the map() method and pair each item inside the map method?
There is a similar question here: Map an array of arrays
However, he context is different because I don't have a nested array to begin with.
var letters = [a, b, c];
var numbers = [1, 2, 3];
var lettersAndNumbers = letters.map((letter) => {
numbers.forEach((number) => {
return letter, number;
);
});
// lettersAndNumbers = [[a, 1], [b, 2], [c, 3]]
Thank you for any tips, hints, or solutions!
To do this, use the following
var letters = ['a','b','c'];
var numbers = [1, 2, 3];
var letterAndNumbers = letters.map((letter,index) => {
return [letter,numbers[index]];
})
And if you print it, you will receive the following output
console.log(letterAndNumbers)
[ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ]
The second parameter of .map() is Index. Make use of it for retrieve a numbers[i] by that iterating index:
const letters = ["a", "b", "c"];
const numbers = [1, 2, 3];
const lettersAndNumbers = letters.map((a, i) => [a, numbers[i]]);
console.log(lettersAndNumbers)
// lettersAndNumbers = [[a, 1], [b, 2], [c, 3]]
I would use a map but here is a reduce just for the sake of it.
var letters = ['a', 'b', 'c'];
var numbers = [1, 2, 3];
var lettersAndNumbers = (letters, numbers) => letters.reduce((results, letter, index) => {
results.push([letter, numbers[index]]);
return results;
}, []);
console.log(lettersAndNumbers(letters, numbers));

How to compare two arrays using lodash (the order matters)

var arr1=[3,4,5,6,7,1,9];
var arr2=[1,3,4,6,7,5,9];
I want to compare arr2 to arr1. But the methods difference() and intersection() only seem to find if the two arrays have the same elements or not. I want to compare the two arrays spot by spot like arr1[0] to arr2[0], arr1[1] to arr2[1]. And it should show:
intersection: 6,7,9
difference: 1,3,4,5
How can I achieve this?
You can do this in lodash by zipping both arrays, filtering, and than taking the last item of each pair. The comperator for intersection is that the pair is equal. The comperator for difference is that the pair are not equal.
const arr1 = [3,4,5,6,7,1,9];
const arr2 = [1,3,4,6,7,5,9];
const compare = (comperator) => (arr1, arr2) =>
_.zip(arr1, arr2)
.filter(comperator)
.map(_.last);
const eq = _.spread(_.eq);
const intersection = compare(eq);
const difference = compare(_.negate(eq));
console.log('intersection ', intersection(arr1, arr2));
console.log('difference ', difference(arr1, arr2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
You could iterate both arrays in parallel and sort them into two seperate Sets:
function* parallel(a, b) {
for(let i = 0; i < a.length || i < b.length; i++)
yield [ a[i], b[i] ];
}
const intersection = new Set,
difference = new Set;
for(const [a, b] of parallel(arr1, arr2)) {
if(a === b)
intersection.add(a);
else
difference.add(a).add(b);
}
console.log([...intersection], [...difference]);
This also could be solved with reduce:
var arr1 = [3, 4, 5, 6, 7, 1, 9];
var arr2 = [1, 3, 4, 6, 7, 5, 9];
const f = (a, b) => b.reduce((r,c,i) => (a[i] == c ?
r.intersection.push(c) :
r.difference.push(c), r), {intersection: [], difference: []})
console.log(f(arr1, arr2))
Where you start with a pre-set accumulator object and compare each array value using the index.
You could use xor from lodash and it will return an empty array if the arrays have the same elements.
const a1= ['a', 'b', 'd']
const a2= ['d', 'b', 'a']
_.xor(a1, a2).length;//0
Why don't you write your own utility function that checks equality of the sequence? Something like:
export function sequenceEqual<T>(firstSequence: T[], secondSequence: T[]): boolean {
if(!firstSequence || !secondSequence) return false;
return firstSequence.every(
(d, i) => d === secondSequence[i]
);
}
This way you can just return boolean. There is no need to perform an extra step to check if the code returned some array or number or whatever, what is length of the returned type, which number it is etc. You just ask are my sequences equal and get true or false.
One more benefit is that you are not dependent on some library. Unless they have sequenceEqual so that you don't have to write from scratch, just call it, but I couldn't find it yet in Lodash.

How to create a key value array from two arrays

I have two arrays with the same number of elements which maps 1:1
const array1 = [1, 3, 2]
const array2 = [U2, U1, U3]
How can I generate a new array (or map) from array1 & array2 and have something like this ?
const result = [[1, U1], [2, U2], [3, U3]]
You can also use Array.forEach(). Before that you can sort the array1 array and then get the corresponding value from array2 prefixed with U to get the desired output:
const array1 = [1, 3, 2];
const array2 = ['U2', 'U1', 'U3'];
const result = [];
array1.sort(function(a,b){
return a-b;
})
array1.forEach((elem, index) => result.push([elem, array2[array2.indexOf('U'+elem)]]));
console.log(result);
If the prefix is not always U then this can be used:
const array1 = [1, 3, 2];
const array2 = ['U2', 'U1', 'U3'];
const result = [];
array1.sort(function(a,b){
return a-b;
})
array1.forEach((elem) => {
var array2Val = array2.find(val => val.indexOf(elem) !== -1);
result.push([elem, array2Val]);
});
console.log(result);
You could group the arrays by the numerical value of each item.
var array1 = [1, 3, 2],
array2 = ['U2', 'U1', 'U3'],
result = Object.values([array1, array2].reduce(
(o, a) => {
a.forEach(v => {
var k = v.toString().match(/\d+$/)[0];
(o[k] = o[k] || []).push(v);
});
return o;
},
Object.create(null)
));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Join two arrays conditionally?

I wanted to join 2 arrays of the same length. However I want to join each element of with it's counterpart and produce a new array with the combined values.
// will always be string
var array = [a, b, c, d]
// Will always be number
var array2 = [1, 2, 0, 4,]
var output = [a1, b2, c0, d4]
I then want to edit the output array removing any values of 0.
So my final output should be:
var result = [a1, b2, d4]
Any thoughts and suggestions much appreciated.
Use map and filter
var result = array.map( (s, i) => [s , array2[i]] ) //combine values
.filter( s => s[1] != 0 ) //filter out 0s
.map( s => s.join("") ); //join them
Demo
// will always be string
var array = ["a", "b", "c", "d"];
// Will always be number
var array2 = [1, 2, 0, 4, ];
var result = array.map((s, i) => [s, array2[i]]) //combine values
.filter(s => s[1] != 0) //filter out 0s
.map(s => s.join("")); //join them
console.log(result);
Check this repl: https://repl.it/#Freundschaft/MeagerNocturnalFormats
// will always be string
var array = ["a", "b", "c", "d"]
// Will always be number
var array2 = [1, 2, 0, 4,]
function joinArraysCustom (firstArray, secondArray){
if(firstArray.length !== secondArray.length){
throw new Error('Arrays must match');
}
return firstArray.map(function(value, index){
return "" + value + secondArray[index];
}).filter(value => !value.endsWith('0'))
}
console.log(joinArraysCustom (array, array2));
You may use .reduce() and .push():
var arr1 = ['a', 'b', 'c', 'd'];
var arr2 = [1, 2, 0, 4];
function createArray(s, n) {
return n.reduce((a, c, i) => (
/* combine and push if current value is not zero
* otherwise return same array
*/
c != 0 ? (a.push(c + s[i]), a) : a
), []);
}
console.log(createArray(arr1, arr2));
Useful Resources:
Array.prototype.reduce()
Array.prototype.push()
Arrow functions
Comma Operator

Categories

Resources