How to create Generic Map/Zip Function that Transpose N Arrays - javascript

I have N Arrays. How can I create a generic Map/Zip function that can transpose N number of arrays together. Please see code below for example.
Also, how can i make it work for multidimensional arrays.
Thank you.
// A Arrays
const arrayA1 = [{name: "James"}, {name: "John"}, {name: "Jack"}]
const arrayA2 = [{age: 10}, {age: 20}, {age: 12}]
// B Arrays
const arrayB1 = [{name: "James"}, {name: "John"}, {name: "Jack"}]
const arrayB2 = [{age: 10}, {age: 20}, {age: 12}]
const arrayB3 = [{height: 150}, {height: 200}, {height: 180}]
const result = {}
const result1 = {}
// Transpose A Arrays Only (does not work for B Arrays)------ How can i make the SAME function work for both A and B arrays
arrayA1.map((x, y) => {
let abc = [x, arrayA2[y]];
result1[y] = abc;
result[x.name] = arrayA2[y]
})
console.log(result);
// { James: { age: 10 }, John: { age: 20 }, Jack: { age: 12 } }
// WHICH IS BETTER IMPLEMENTATION >>>>>> result or result1 >> I intend to send to mongodb
console.log(result1);
/*
{ '0': [ { name: 'James' }, { age: 10 } ],
'1': [ { name: 'John' }, { age: 20 } ],
'2': [ { name: 'Jack' }, { age: 12 } ] }
*/

A better result structure would be an array of objects, like
[
{name: xxx, age: yyy},
{name: xxx, age: yyy},
{name: xxx, age: yyy}
]
Here's code to generate it:
// A Arrays
const arrayA1 = [{name: "James"}, {name: "John"}, {name: "Jack"}]
const arrayA2 = [{age: 10}, {age: 20}, {age: 12}]
// B Arrays
const arrayB1 = [{name: "James"}, {name: "John"}, {name: "Jack"}]
const arrayB2 = [{age: 10}, {age: 20}, {age: 12}]
const arrayB3 = [{height: 150}, {height: 200}, {height: 180}]
//
zip = (...arrays) => arrays[0].map((_, n) => arrays.map(a => a[n]));
merge = (x, y) => Object.assign(x, y);
zipMerge = (...arrays) => zip(...arrays).map(props => props.reduce(merge, {}))
//
console.log(zipMerge(arrayA1, arrayA2))
console.log(zipMerge(arrayB1, arrayB2, arrayB3))

Related

how to filter multiple values from an array in javascript

I have an array of json elements. and I want to filter the array based on the specific values. below is the array.
var arr = [
{name: bobby, id: 1, age: 23},
{name: charls, id: 2, age: 28},
{name: indi, id: 3, age: 23},
{name: charlie, id: 4, age: 25}]
from the above array I want to filter only staff whose names are bobby && indi. I have tried below code.
var filteredArray;
for (var i =0 ; i < arr.length; i++){
if(arr[i].name === 'bobby' || arr[i].name === 'indi'){
filteredArray.push(arr[i]);
}
}
but through the above code, I need to mention OR(||) conditions too many times and these number of names can change like 1 time I want only staff with Bobby name and other time I want Bobby, Indi and Charlie. is there a way to make it dynamic. if yes, please let me know. Thanks in advance.
You can store names that needs to be filters in an array and then check if name exists in array or not
eg.
var arr = [
{name: "bobby", id: 1, age: 23},
{name: "charls", id: 2, age: 28},
{name: "indi", id: 3, age: 23},
{name: "charlie", id: 4, age: 25}
]
const names = ["bobby", "indi"];
const filtered = arr.filter((item)=>{
return names.includes(item.name)
});
console.log(filtered)
For older(eg. IE11) browsers -
var arr = [
{name: "bobby", id: 1, age: 23},
{name: "charls", id: 2, age: 28},
{name: "indi", id: 3, age: 23},
{name: "charlie", id: 4, age: 25}
]
const names = ["bobby", "indi"];
const filtered = [];
for(var i =0; i<arr.length - 1; i++){
if(names.indexOf(arr[i].name) > -1){
filtered.push(arr[i])
}
}
console.log(filtered)
You can use Array.includes() to filter items as followings:
var arr = [
{name: 'bobby', id: 1, age: 23},
{name: 'charls', id: 2, age: 28},
{name: 'indi', id: 3, age: 23},
{name: 'charlie', id: 4, age: 25}
]
const keywords = ['bobby', 'indi'] // You can add keywords to be filtered to this array to make it dynamic
const filtered = arr.filter(item => keywords.includes(item.name))
console.log(filtered)
You could create an array of names you want to filter and then:
if you want to stick to pre-ES6 coding:
var arr = [{
name: 'bobby',
id: 1,
age: 23
},
{
name: 'charls',
id: 2,
age: 28
},
{
name: 'indi',
id: 3,
age: 23
},
{
name: 'charlie',
id: 4,
age: 25
}
];
var names = ['bobby', 'indi'];
var filteredArray = [];
for (var i = 0; i < arr.length; i++) {
if (names.indexOf(arr[i].name) > -1) filteredArray.push(arr[i]);
}
console.log(filteredArray);
or, if you are willing to switch to ES6+ coding:
const arr = [{
name: 'bobby',
id: 1,
age: 23
},
{
name: 'charls',
id: 2,
age: 28
},
{
name: 'indi',
id: 3,
age: 23
},
{
name: 'charlie',
id: 4,
age: 25
}
];
const names = ['bobby', 'indi'];
const filteredArray = arr.filter(item => names.includes(item.name));
console.log(filteredArray);

Move repeating object property into a single property in array of objects

Basically I have this JavaScript array:
const a = [
{name: 'Foo', place: 'US', age: 15},
{name: 'Foo', place: 'UK', age: 21},
{name: 'Bar', place: 'Canada', age: 20},
{name: 'Bar', place: 'China', age: 22}
];
What is the fastest way to make it look like this? (Where the name becomes a single object property in the "a" array). How would I iterate over the array?
const a = [
{
name: 'Foo',
data: [
{
place: 'US', age: 15
},
{
place: 'UK', age: 21
}
]
},
{
name: 'Bar',
data: [
{
place: 'Canada', age: 20
},
{
place: 'China', age: 22
}
]
}
];
Thank you!
You can make use of reduce function to group data based on name property and then take Object.values.
var a = [
{name: 'Foo', place: 'US', age: 15},
{name: 'Foo', place: 'UK', age: 21},
{name: 'Bar', place: 'Canada', age: 20},
{name: 'Bar', place: 'China', age: 22}
];
var result = Object.values(a.reduce((acc, {name, ...rest})=>{
acc[name] = acc[name] || {name, data:[]};
acc[name].data = [...acc[name].data, rest];
return acc;
},{}));
console.log(result);
One way could be to use an ES6 Map. You can use .reduce() to accumulate the objects in a to the Map. Each name can be a key in the map and each value within the map will be an array of objects which have that key as a name. Once you have built the Map, you can use Array.from() to convert the Map to an array, while also providing a mapping function to convert the entries [name, data[]] to objects while the Map to array conversion occurs.
See example below:
const a = [
{name: 'Foo', place: 'US', age: 15},
{name: 'Foo', place: 'UK', age: 21},
{name: 'Bar', place: 'Canada', age: 20},
{name: 'Bar', place: 'China', age: 22}
];
const res = Array.from(a.reduce((m, {name, ...r}) => {
return m.set(name, (m.get(name) || []).concat(r));
}, new Map), ([name, data]) => ({name, data}));
console.log(res);

Javascript get all values of object

I want to get all name from the array of data. Is there any way to do it without using an iterator?
const data = [
{name: 'Rushabh', age: 22},
{name: 'Bonny', age: 24}
]
console.log(Object.values(data));
Try this:
const data = [
{name: 'Rushabh', age: 22},
{name: 'Bonny', age: 24}
]
const names = data.map(({name}) => name)
console.log(names);
the names will include the list of names.
For getting only a single property, you need to map this property directly.
const
data = [{ name: 'Rushabh', age: 22 }, { name: 'Bonny', age: 24 }],
result = data.map(({ name }) => name); // get only name
console.log(result);
Without some kind of iterator you can not do that. You can use map() with short hand property.
const data = [
{name: 'Rushabh', age: 22},
{name: 'Bonny', age: 24}
]
const name = data.map(({name}) => name);
console.log(name);
Use Array.map() and extract the name property:
const data = [
{name: 'Rushabh', age: 22},
{name: 'Bonny', age: 24}
]
console.log(data.map(x => x.name));
If you are using JQuery, do this:
const data = [
{name: 'Rushabh', age: 22},
{name: 'Bonny', age: 24}
]
var names = $.map( data, function(item, key) { return item.name; } );
// names : ['Rushabh', 'Bonny']

UnderscoreJS: trim array of objects based on condition

I have an array of JSON object as shown below:
var data = [
{name: '', age: 12},
{name: 'bcd', age: 15},
{name: 'cdf', age: 13},
{name: '', age: 11},
{name: 'fgh', age: 8},
{name: '', age: 10},
];
using underscore I want to trim this object in such a way that it should return:
[{name: 'bcd', age: 15},
{name: 'cdf', age: 13},
{name: '', age: 11},
{name: 'fgh', age: 8}]
I tried with below code:
var firstIndex = _.indexOf(data, _.find(data, function(d){ return d.name !== ''; }));
var lastIndex = _.indexOf(data, _.find(data.slice().reverse(), function(d){ return d.name !== ''; }));
console.log(data.slice(firstIndex, lastIndex + 1) );
But I think, there should be a better way than this.
Here is the JSFiddle
Edit:
I want all data from the top and bottom to be trimmed where name is blank. But not in middle of the array element.
Same as string.Trim() method. when I apply trim on " one two three " text, it will remove blank space from the starting and end but not the space between words.
your logic is fine, just use _.findLastIndex() instead of using _.findIndex() on the reversed array:
const data = [
{name: '', age: 7},
{name: '', age: 12},
{name: 'bcd', age: 15},
{name: 'cdf', age: 13},
{name: '', age: 11},
{name: 'fgh', age: 8},
{name: '', age: 10},
{name: '', age: 12},
{name: '', age: 14},
];
function trimArray(predicate, arr) {
const start = _.findIndex(arr, predicate);
const end = _.findLastIndex(arr, predicate);
return arr.slice(start, end + 1);
}
const result = trimArray((o) => o.name !== '', data);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
Looks like you want to return the array without first and last item, then use slice
var trimmedData = data.slice( 1, data.length - 1 );
I want all data from the top and bottom to be trimmed where name is
blank. But not in middle of the array element.
Define a trimLeftFn
var trimLeftFn = arr => {
var hasValue = false;
arr = arr.filter( s => {
hasValue = hasValue || s.name.length > 0;
return hasValue;
});
return arr;
};
var trimmedData = trimLeftFn( trimLeftFn (data ).reverse() ).reverse();
Demo
var data = [
{name: '', age: 12},
{name: 'bcd', age: 15},
{name: 'cdf', age: 13},
{name: '', age: 11},
{name: 'fgh', age: 8},
{name: '', age: 10},
];
var trimLeftFn = arr => {
var hasValue = false;
arr = arr.filter(s => {
hasValue = hasValue || s.name.length > 0;
return hasValue;
});
return arr;
};
var trimmedData = trimLeftFn(trimLeftFn(data).reverse()).reverse();
console.log(trimmedData);

Removing duplicates from JSON array by a value in each JSON object in array

If there are two JSON objects in an array with same value for a particular field, then I want to mark them as duplicate. I want to remove one of them. Similarly, when there are multiple duplicate, I only want to keep the last object(latest).If this is input:
names_array = [
{name: "a", age: 15},
{name: "a", age: 16},
{name: "a", age: 17},
{name: "b", age: 18}
{name: "b", age: 19}];
I want the output to be
names_array_new =
{name: "a", age: 17},
{name: "b", age: 19}];
I have searched for this but only found how to remove duplicates when entire objects are same.
This should do it:
names_array = [
{name: "a", age: 15},
{name: "a", age: 16},
{name: "a", age: 17},
{name: "b", age: 18},
{name: "b", age: 19}];
function hash(o){
return o.name;
}
var hashesFound = {};
names_array.forEach(function(o){
hashesFound[hash(o)] = o;
})
var results = Object.keys(hashesFound).map(function(k){
return hashesFound[k];
})
The hash function decides which objects are duplicates, the hashesFound object stores each hash value together with the latest object that produced that hash, and the results array contains the matching objects.
A slightly different approach:
var names_array = [
{ name: "a", age: 15 },
{ name: "a", age: 16 },
{ name: "a", age: 17 },
{ name: "b", age: 18 },
{ name: "b", age: 19 }
];
var names_array_new = names_array.reduceRight(function (r, a) {
r.some(function (b) { return a.name === b.name; }) || r.push(a);
return r;
}, []);
document.getElementById('out').innerHTML = JSON.stringify(names_array_new, 0, 4);
<pre id="out"></pre>
var names_array = [
{name: "a", age: 15},
{name: "a", age: 16},
{name: "a", age: 17},
{name: "b", age: 18},
{name: "b", age: 19}];
function removeDuplicate(arr, prop) {
var new_arr = [];
var lookup = {};
for (var i in arr) {
lookup[arr[i][prop]] = arr[i];
}
for (i in lookup) {
new_arr.push(lookup[i]);
}
return new_arr;}
var newArray = removeDuplicate(names_array, 'name');
console.log("Result "+newArray);
Array.from(new Set(brand.map(obj => JSON.stringify(obj)))).map(item => JSON.parse(item))

Categories

Resources