Splitting a Map instance into two separate arrays - javascript

I'm trying to split an instance of Map into separate arrays. An example of the Map instance I have:
new Map([
["Guatemala", 7],
["Albania", 7],
["Finland", 3],
["Canada", 12],
["Japan", 21],
...
]);
There's more data, but just wanted to show a small sample.
I produced it from the raw data I get from an API in JSON format:
[
{
id: 1,
import_country: "Argentina",
model: "riolet",
make: "Audi",
sold_by: "Huey Bagster",
sale_price: 18643,
},
{
id: 2,
import_country: "China",
model: "MKX",
make: "Lincoln",
sold_by: "Wolf Coller",
sale_price: 16850,
},
{
id: 3,
import_country: "Portugal",
model: "Coupe Quattro",
make: "Audi",
sold_by: "Doroteya McLewd",
sale_price: 13733,
},
]
So I took the import_country and counted the number of times it appeared and created map as an instance of Map.
In order to get the keys and values of map in separate arrays, I tried the following:
map.forEach(key, value){
country.append(key);
numCountry.append(value);
}
where country and numCountry are separate arrays.
My end desired output is:
country = ["Guatemala", "Albania"...] and
numCountry = [7, 7, ...]

If your map is an instance of Map, then use its keys and values methods:
const map = new Map([
["Guatemala", 7],
["Albania", 7],
["Finland", 3],
["Canada", 12],
["Japan", 21],
]);
const countries = [...map.keys()];
const numCountries = [...map.values()];
console.log(countries);
console.log(numCountries);

Kindly take as sample, modify according to your need.
You can use Object.reduce(data) to loop over data and update count for countries.
const data = [
{
id: 1,
import_country: "Argentina",
model: "riolet",
make: "Audi",
sold_by: "Huey Bagster",
sale_price: 18643,
},
{
id: 2,
import_country: "China",
model: "MKX",
make: "Lincoln",
sold_by: "Wolf Coller",
sale_price: 16850,
},
{
id: 3,
import_country: "Portugal",
model: "Coupe Quattro",
make: "Audi",
sold_by: "Doroteya McLewd",
sale_price: 13733,
},
{
id: 4,
import_country: "Portugal",
model: "Coupe Quattro",
make: "Audi",
sold_by: "Doroteya McLewd",
sale_price: 13733,
},
];
const map = data.reduce((m, { id, import_country }) => {
if (!m[import_country]) m[import_country] = 0;
m[import_country] += 1;
return m;
}, {});
console.log(map);
const counties = Object.keys(map)
const numCounts = Object.values(map)
console.log(counties)
console.log(numCounts)
//OR:
let countries2 = [],
numCountries2 = [];
Object.entries(map).forEach(([key, value]) => {
countries2.push(key)
numCountries2.push(value)
});
console.log(countries2);
console.log(numCountries2);

Use JSON.parse to convert it to an array then just loop and push id of each item on country code array and name on ct array
var str = `[
{
"id": 1,
"import_country": "Argentina",
"model": "riolet",
"make": "Audi",
"sold_by": "Huey Bagster",
"sale_price": 18643
},
{
"id": 2,
"import_country": "China",
"model": "MKX",
"make": "Lincoln",
"sold_by": "Wolf Coller",
"sale_price": 16850
},
{
"id": 3,
"import_country": "Portugal",
"model": "Coupe Quattro",
"make": "Audi",
"sold_by": "Doroteya McLewd",
"sale_price": 13733
}
]`
var arr = JSON.parse(str);
var ct = [];
var code = [];
for (var i = 0; i < arr.length; i++) {
ct.push(arr[i].import_country);
code.push(arr[i].id)
}
console.log(ct); //countries
console.log(code); //codes

Related

How to create every combination possible between two array of objects?

I have two arrays of objects, i.e. origin and destination. I am trying to find out all possible combinations that can be made from the two arrays to make a final array.
Example:
origin = [
{
id: 1,
regionName: "Africa North"
},
{
id: 2,
regionName: "Africa West"
}
];
destination: [
{
id: 5,
regionName: "Gulf"
},
{
id: 8,
regionName: "Middle East"
},
{
id: 9,
regionName: "Central America"
}
]
The final array should give me,
finalArray = [
{
originRegion: "Africa North",
destinationRegion: "Gulf",
ts: "1606370160"
},
{
originRegion: "Africa North",
destinationRegion: "Middle East",
ts: "1606370160"
},
{
originRegion: "Africa North",
destinationRegion: "Central America",
ts: "1606370160"
},
{
originRegion: "Africa West",
destinationRegion: "Gulf",
ts: "1606370160"
},
{
originRegion: "Africa West",
destinationRegion: "Middle East",
ts: "1606370160"
},
{
originRegion: "Africa West",
destinationRegion: "Central America",
ts: "1606370160"
},
]
I tried looking for some Permutations and combinations on two array of objects but didn't find get any suitable answer.
This is what I am trying:
useEffect(() => {
var origin = [
{
id: 1,
regionName: "Africa North"
},
{
id: 2,
regionName: "Africa West"
}
];
var destination = [
{
id: 5,
regionName: "Gulf"
},
{
id: 8,
regionName: "Middle East"
},
{
id: 9,
regionName: "Central America"
}
];
var finalArray = []
for (var i = 0; i < origin.length; i++) {
for (var j = 0; j < destination.length; j++) {
finalArray.push(origin[i].regionName + destination[j].regionName)
}
}
console.log("finalArray", finalArray)
}, []);
Thank you in advance.
Looks like you have the double looping part, but the object you are pushing into your array isn't what you say you expect. You are doing simple string concatenation.
origin[i].regionName + destination[j].regionName
Here is what I think is a more "react" way to loop over the data and return a result array. Reduce the origin array into a new array, mapping in the combined object with the destination array.
origin.reduce(
(result, origin) => [
...result,
...destination.map((destination) => ({
originreagion: origin.regionName,
destinationRegion: destination.regionName,
ts: "1606370160" // <-- set your real timestamp here
}))
],
[]
);
const origin = [
{
id: 1,
regionName: "Africa North"
},
{
id: 2,
regionName: "Africa West"
}
];
const destination = [
{
id: 5,
regionName: "Gulf"
},
{
id: 8,
regionName: "Middle East"
},
{
id: 9,
regionName: "Central America"
}
];
const result = origin.reduce(
(result, origin) => [
...result,
...destination.map((destination) => ({
originreagion: origin.regionName,
destinationRegion: destination.regionName,
ts: "1606370160"
}))
],
[]
);
console.log(result)

How to combine 2 objects into a table by matching their id values?

I would like to know how to combine to two objects together by matching their id values with each other and possibly make it into a table format.
$genres = [
{
"id": 1,
"type": "KPOP",
"music_id": 1,
"created_at": "2020-04-19 10:10:10"
},
{
"id": 3,
"type": "JPOP",
"music_id": 3,
"created_at": "2020-02-14 10:10:10"
},
{
"id": 2,
"type": "OPM",
"music_id": 2,
"created_at": "2020-06-30 10:10:10"
}
];
$countries = [
{
"id": 1,
"country": "South Korea",
"updated_at" : "2020-04-20 10:10:10"
},
{
"id": 3,
"country": "Japan",
"updated_at" : "2020-02-15 10:10:10"
},
{
"id": 2,
"country": "Philippines",
"updated_at" : "2020-07-01 10:10:10"
}
];
The result should be arranged like this (doesn't have to be designed like this, just need to be a simple table):
+----+--------+--------------------+
| 1 | KPOP | South Korea |
+----+--------+--------------------+
| 2 | OPM | Philippines |
+----+--------+--------------------+
| 3 | JPOP | Japan |
+----+--------+--------------------+
My solution however has been fleshing out the wrong combinations like so (not a table yet because I don't know how):
let table = []
for (let i = 0; i < $genres.length; i++) {
table.push({
...$genres,
...$countries.find((countryId) => countryId.id === $genres[i].id )
});
}
console.log(table)
[
{
'0': {
id: 1,
type: 'KPOP',
music_id: 1,
created_at: '2020-04-19 10:10:10'
},
'1': {
id: 3,
type: 'JPOP',
music_id: 3,
created_at: '2020-02-14 10:10:10'
},
'2': {
id: 2,
type: 'OPM',
music_id: 2,
created_at: '2020-06-30 10:10:10'
},
id: 1,
country: 'South Korea',
updated_at: '2020-04-20 10:10:10'
},
{
'0': {
id: 1,
type: 'KPOP',
music_id: 1,
created_at: '2020-04-19 10:10:10'
},
'1': {
id: 3,
type: 'JPOP',
music_id: 3,
created_at: '2020-02-14 10:10:10'
},
'2': {
id: 2,
type: 'OPM',
music_id: 2,
created_at: '2020-06-30 10:10:10'
},
id: 3,
country: 'Japan',
updated_at: '2020-02-15 10:10:10'
},
{
'0': {
id: 1,
type: 'KPOP',
music_id: 1,
created_at: '2020-04-19 10:10:10'
},
'1': {
id: 3,
type: 'JPOP',
music_id: 3,
created_at: '2020-02-14 10:10:10'
},
'2': {
id: 2,
type: 'OPM',
music_id: 2,
created_at: '2020-06-30 10:10:10'
},
id: 2,
country: 'Philippines',
updated_at: '2020-07-01 10:10:10'
}
]
I would like to know how to make this into a table but I am getting confused so far. Thank you in advance!
Create an object from the countries keyed on id. Then iterate the genres and you have an O(1) look up on the country object to match country and genre.
const countryObj = $countries.reduce((obj, x) => { obj[x.id] = x; return obj; }, {});
for(let g of $genres.sort((a, b) => a.id - b.id)) {
const country = countryObj[g.id]
if (country !== undefined) {
console.log([g.id, g.type, country.country].join('|'))
}
}
This assumes all entries in $countries have consistent property names for the country name.
const merged=$genres.map(g=>{
const commonId=$countries.find(c=>c.id===g.id)||{};
return {...g,...commonId}
})
console.log(merged);
With this merged Data. you can create your table!
What you can do is take each ID from $genres and try to map it with an object of countries. And if they match, I created new object with country attribute from countries and all the other attributes from $genres. So your 2 arrays are merged. Sample code below:
let x = [];
$genres = $genres.sort(function(a,b){
return a.id-b.id;
});
x = $genres.map((obj) => {
for(let country of $countries) {
if(country.id == obj.id){
return { 'country': country.country, ...obj }
}
}
});
Now you can use x. If you want to combine two arrays into 1 based on their IDs that can also be done. Replace the return statement to:
return { ...country, ...obj };

Convert an array of arrays to an array of objects with mapped properties

What is the best way of converting an array of arrays to objects so that the indices are replaced with given mapping properties.
For example:
let cars = [
[1, "Honda", "Honda description here"],
[2, "Mercedes", "Mercedes description here"],
[3, "Toyota", "Toyota description here"],
];
let mapping = {
0: 'id',
1: 'name',
2: 'description',
};
So the final result is:
[
{id: 1, name: 'Honda', description: 'Honda description here'},
{id: 2, name: 'Mercedes', description: 'Mercedes description here'},
{id: 3, name: 'Toyota', description: 'Toyota description here'},
];
Use a map command. Note: this code assumes there are mappings for each element of the array.
let cars = [
[1, "Honda", "Honda description here"],
[2, "Mercedes", "Mercedes description here"],
[3, "Toyota", "Toyota description here"],
];
let mapping = {
0: 'id',
1: 'name',
2: 'description',
};
let result = cars.map(a => {
let obj = {};
a.forEach((v,i) => {
obj[mapping[i]] = v;
});
return obj;
});
console.log(result);
You can achieve the merged result by using a combination of:
[].map() on the cars array to loop through its elements.
[].reduce() on each car element to reduce the three value into one object, taking advantage of the ordering you have in the mapping object.
Here is a solution that can be shortened into a one-liner:
let cars = [
[1, "Honda", "Honda description here"],
[2, "Mercedes", "Mercedes description here"],
[3, "Toyota", "Toyota description here"],
];
let mapping = {
0: 'id',
1: 'name',
2: 'description',
};
let result = cars.map((car) => (
car.reduce((acc, cur, i) => (
Object.assign(acc, { [mapping[i]]: cur })
), {})
));
console.log(result);

javascript - merge, combine, transform 2 different arrays of Objects

I can't figure it out how to transform and combine 2 arrays of object.
I have this 2 arrays of objects:
const selectedCourse = [
{
"courseType": [5],
"id": 26,
"title": "Apple Tart with Apricot Glaze",
},
{
"courseType": [3],
"id": 16,
"title": "Classic Caesar Salad",
},
{
"courseType": [1,2],
"id": 10,
"title": "Lobster Bisque",
},
{
"courseType": [3],
"id": 16,
"title": "Classic Caesar Salad",
},
]
const courseTypes = [
{name: "Hors d'oeuvres", id: 0},
{name: "Soup", id: 1},
{name: "Fish", id: 2},
{name: "Salad", id: 3},
{name: "Main course", id: 4},
{name: "Dessert", id: 5}
]
The courseType property inside the first JSON is an array of numbers that corresponds to courseTypes index and property id in the second JSON.
The result for this case should be this:
const result = [
{
courseType: 1,
courseName: "Soup",
courses: [
{
"courseType": [1,2],
"id": 10,
"title": "Lobster Bisque",
}
]
},
{
courseType: 3,
courseName: "Salad",
courses: [
{
"courseType": [1,2],
"id": 10,
"title": "Lobster Bisque",
}
]
},
{
courseType: 3,
courseName: "Fish",
courses: [
{
"courseType": [3],
"id": 16,
"title": "Classic Caesar Salad",
},
{
"courseType": [3],
"id": 16,
},
]
},
{
courseType: 5,
courseName: "Main course",
courses: [
{
"courseType": [5],
"id": 26,
"title": "Apple Tart with Apricot Glaze",
}
]
}
]
The expected result have to combine the 2 arrays by filtering by courseType property.
Assuming, you want all items with selectedCourse, you could take a Map and collect all courses and later greate a new array out of the found values.
This solution includes Fish as well.
const
selectedCourse = [{ courseType: [5], id: 26, title: "Apple Tart with Apricot Glaze" }, { courseType: [3], id: 16, title: "Classic Caesar Salad" }, { courseType: [1, 2], id: 10, title: "Lobster Bisque" }, { courseType: [3], id: 16, title: "Classic Caesar Salad" }],
courseTypes = [{ name: "Hors d'oeuvres", id: 0 }, { name: "Soup", id: 1 }, { name: "Fish", id: 2 }, { name: "Salad", id: 3 }, { name: "Main course", id: 4 }, { name: "Dessert", id: 5 }],
map = selectedCourse.reduce((m, o) => o.courseType.reduce((n, id) => n.set(id, [...(n.get(id) || []), o]), m), new Map),
result = courseTypes.reduce(
(r, { name: courseName, id: courseType }) => (map.get(courseType) || []).reduce((s, courses) => s.concat({ courseType, courseName, courses }), r),
[]
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use map and filter like this:
const selectedCourse = [ { "courseType": [5], "id": 26, "title": "Apple Tart with Apricot Glaze", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, { "courseType": [1,2], "id": 10, "title": "Lobster Bisque", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, ]
const courseTypes = [ {name: "Hors d'oeuvres", id: 0}, {name: "Soup", id: 1}, {name: "Fish", id: 2}, {name: "Salad", id: 3}, {name: "Main course", id: 4}, {name: "Dessert", id: 5} ];
const result = courseTypes.map(courseType => ({
courseType: courseType.id,
courseName: courseType.name,
courses: selectedCourse.filter(course => course.courseType.includes(courseType.id))
})).filter(extended => extended.courses.length);
console.log(JSON.stringify(result, null, 2));
Explanation:
courseTypes.map iterates over your second input array and for each type it finds in selectedCourse which courses match with that particular type.
It uses .filter to collect those matches. The filter callback uses includes to determine if there is a match -- it returns a boolean, exactly what the filter callback expects as return value.
This filtered array is then added to an object literal that also defines the other two properties courseType and courseName. That new object is what the course type is mapped to. courseTypes.map returns an array of those objects.
Finally that result may have entries that have an empty courses array. Those are filtered out with another call to .filter. If the length of that courses array is non zero, the object is kept, otherwise it is kicked out of the result.
For older browsers
Here is the same code made compatible with older browsers (no arrow functions, no includes, which were introduced in ES2015):
const selectedCourse = [ { "courseType": [5], "id": 26, "title": "Apple Tart with Apricot Glaze", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, { "courseType": [1,2], "id": 10, "title": "Lobster Bisque", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, ]
const courseTypes = [ {name: "Hors d'oeuvres", id: 0}, {name: "Soup", id: 1}, {name: "Fish", id: 2}, {name: "Salad", id: 3}, {name: "Main course", id: 4}, {name: "Dessert", id: 5} ];
const result = courseTypes.map(function (courseType) {
return {
courseType: courseType.id,
courseName: courseType.name,
courses: selectedCourse.filter(function (course) {
return course.courseType.indexOf(courseType.id) > -1;
})
};
}).filter(function (extended) {
return extended.courses.length;
});
console.log(JSON.stringify(result, null, 2));
while "trincot" code is work fine for chrome and Mozila but it will not work in IE edge and IE 10 and below you need to convert it in pure javascript. below is code which will work in all browser.
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value: function(searchElement, fromIndex) {
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
// 1. Let O be ? ToObject(this value).
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If len is 0, return false.
if (len === 0) {
return false;
}
// 4. Let n be ? ToInteger(fromIndex).
// (If fromIndex is undefined, this step produces the value 0.)
var n = fromIndex | 0;
// 5. If n ≥ 0, then
// a. Let k be n.
// 6. Else n < 0,
// a. Let k be len + n.
// b. If k < 0, let k be 0.
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
function sameValueZero(x, y) {
return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
}
// 7. Repeat, while k < len
while (k < len) {
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
// b. If SameValueZero(searchElement, elementK) is true, return true.
if (sameValueZero(o[k], searchElement)) {
return true;
}
// c. Increase k by 1.
k++;
}
// 8. Return false
return false;
}
});
}
var selectedCourse = [{ "courseType": [5], "id": 26, "title": "Apple Tart with Apricot Glaze" }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad" }, { "courseType": [1, 2], "id": 10, "title": "Lobster Bisque" }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad" }];
var courseTypes = [{ name: "Hors d'oeuvres", id: 0 }, { name: "Soup", id: 1 }, { name: "Fish", id: 2 }, { name: "Salad", id: 3 }, { name: "Main course", id: 4 }, { name: "Dessert", id: 5 }];
var result = courseTypes.map(function (courseType) {
return {
courseType: courseType.id,
courseName: courseType.name,
courses: selectedCourse.filter(function (course) {
return course.courseType.includes(courseType.id);
})
};
}).filter(function (extended) {
return extended.courses.length;
});
console.log(JSON.stringify(result, null, 2));

Normalizr with nested array of objects

I have a nested array of objects like this:
var matchs = [
{
id: 10689,
sport: 'Tennis',
players: [
{
id: 22,
name:'Rafa Nadal',
country: 'Spain',
odds: [
{id: 1, bookie_1: 1.60},
{id: 2, bookie_2: 1.61},
{id: 3, bookie_3: 1.62},
]
},
{
id: 23,
name:'Roger Federer',
country: 'Spain',
odds: [
{id: 4, bookie_1: 2.60},
{id: 5, bookie_2: 2.61},
{id: 6, bookie_3: 2.62},
]
}
]
},
{
id: 12389,
sport: 'Tennis',
players: [
{
id: 45,
name:'Fernando Verdasco',
country: 'Spain',
odds: [
{id: 7, bookie_1: 2.60},
{id: 8, bookie_2: 2.61},
{id: 9, bookie_3: 2.62},
]
},
{
id: 65,
name:'Andy Murray',
country: 'Spain',
odds: [
{id: 10, bookie_1: 1.60},
{id: 11, bookie_2: 1.61},
{id: 12, bookie_3: 1.62},
]
}
]
}
];
I want to use normalizr to simplify array and use with redux. I have read the Normalizr documentation but it has few examples and I do not know what I am doing wrong.
I have tried the following code without success. The result I get is an array with undefined.
import { normalize, schema } from 'normalizr';
const match = new schema.Entity('matchs');
const player = new schema.Entity('players');
const odd = new schema.Entity('odds');
match.define({
player: [player],
odd: [odd]
});
console.log(normalize(matchs, [match]));
I need something like this:
{
result: "123",
entities: {
"matchs": {
"123": {
id: "123",
players: [ "1","2" ],
odds: [ "1", "2" ]
}
},
"players": {
"1": { "id": "1", "name": "Rafa Nadal" },
"2": { "id": "2", "name": "Andy Murray" }
},
"odds": {
"1": { id: "1", "bookie_1": "1.20" }
"2": { id: "2", "bookie_2": "1.21" }
"3": { id: "3", "bookie_3": "1.22" }
}
}
}
I cannot find a straight solution using only normalizr, so my only choice is to pre-format the data before passing to the normalizer.
const preformattedData = data.map(sport => {
const oddArrays = sport.players.map(player => player.odds || []);
return {
...sport,
odds: [].concat.apply([], oddArrays)
}
})
const odd = new schema.Entity('odds')
const player = new schema.Entity('players',
{
odds: [ odd ]
}
)
const sport = new schema.Entity('sports',
{
players: [ player ],
odds: [odd]
}
)
const normalizedData = normalize(preformattedData, [ sport ]);
Demo: https://codesandbox.io/s/20onxowzwn
I think this is what you need
const odd = new schema.Entity('odds');
const player = new schema.Entity('players' , { odds: [ odd]});
const match = new schema.Entity('matchs', {players: [player]});
but the result will be different because your json it is structured like this, I mean, the odds key is child of players, not of matches, therefore the result will be this way.
Just take a look at the console
Here is a solution with latest version of normalizr
const odds = new schema.Entity("odds");
const players = new schema.Entity("players", {
odds: [odds]
});
const matches = new schema.Entity("matches", { players: [players] });
const normalizedData = normalize(data, [matches]);
It would group data in your question as
{
"entities": {
"odds": {
"1": {
"id": 1,
"bookie_1": 1.6
}
},
"players": {
"22": {
"id": 22,
"name": "Rafa Nadal",
"country": "Spain",
"odds": [
1,
2,
3
]
}
},
"matches": {
"10689": {
"id": 10689,
"sport": "Tennis",
"players": [
22,
23
]
}
}
},
"result": [
10689
]
}
You can achieve your desired result by tweaking the process and merge strategies. I don't have time to do the leg work for you, but I explain the approach in detail here:
https://medium.com/#JustinTRoss/normalizing-data-into-relational-redux-state-with-normalizr-47e7020dd3c1

Categories

Resources