Convert an array of string key pairs to an object - javascript

I have this data structure:
[
'ecl:hzl byr:1926 iyr:2010,pid:221225902 cid:61 hgt:186cm eyr:2021 hcl:#7d3b0c',
'hcl:#efcc98 hgt:178 pid:433543520,eyr:2020 byr:1926,ecl:blu cid:92,iyr:2010',
'iyr:2018,eyr:2026,byr:1946 ecl:brn,hcl:#b6652a hgt:158cm,pid:822320101'
]
I'm looking to convert those array values to objects instead of strings. I understand I need to do a map with a split(' '), but unsure of the logic inside of there.
Desired output:
[
{ecl: 'hzl', byr: 1926},
{hcl: '#efcc98', byr: 1926}
]
etc. with all of the fields.
I've tried:
.map(values => { let pair = values.split(':'); obj[pair[0]] = pair[1]; return obj })
But seem to get the same object repeated over and over, from the first index of the array.

If you're looking to get each element of the array as a separate object then try this:
const input = [
'ecl:hzl byr:1926 iyr:2010,pid:221225902 cid:61 hgt:186cm eyr:2021 hcl:#7d3b0c',
'hcl:#efcc98 hgt:178 pid:433543520,eyr:2020 byr:1926,ecl:blu cid:92,iyr:2010',
'iyr:2018,eyr:2026,byr:1946 ecl:brn,hcl:#b6652a hgt:158cm,pid:822320101'
]
const output = input.map((string) => { // for each string in array
const pairs = string.split(/[\ ,]/); // split by space or comma
const object = {}; // create an object
for (pair of pairs) { // for each pair in string
const parts = pair.split(":"); // split by colon
if (parts.length == 2) { // if you get 2 parts after splitting
object[parts[0]] = parts[1]; // use the first part as a key and the second as a value
}
}
return object;
});
console.log(output);

Try this
array = array.map(val => {
var obj = {}
val.split(' ').forEach(keyValPair => {
var keyVal = keyValPair.split(':')
obj[keyVal[0]] = keyVal[1];
})
return obj;
})

You can use Object.fromEntries.
const arr = [
'ecl:hzl byr:1926 iyr:2010,pid:221225902 cid:61 hgt:186cm eyr:2021 hcl:#7d3b0c',
'hcl:#efcc98 hgt:178 pid:433543520,eyr:2020 byr:1926,ecl:blu cid:92,iyr:2010',
'iyr:2018,eyr:2026,byr:1946 ecl:brn,hcl:#b6652a hgt:158cm,pid:822320101'
];
const res = arr.map(x => Object.fromEntries(x.replace(/,/g, ' ')
.split(' ').map(y => y.split(':'))));
console.log(res);

Related

How to convert json object keys into different arrays removing the duplicate

I'm having the JSON like this i need to group this JSON with all the keys in JSON object and value should in array (excluding duplicates).
var people = [
{sex:"Male", name:"Jeff"},
{sex:"Female", name:"Megan"},
{sex:"Male", name:"Taylor"},
{sex:"Female", name:"Madison"}
];
My output should be like
{"sex":["Male","Female"],"name":["Jeff","Megan","Taylor","Madison"]}
how we can able to achieve this
function getValues(array) {
var result = {};
array.forEach(obj => {
Object.keys(obj).forEach(key => {
if(!Array.isArray(result[key]))
result[key] = [];
result[key].push(obj[key]);
})
})
return result;
}
You could use the Array.reduce() method to transform your array into a single object:
var people = [
{sex:"Male", name:"Jeff"},
{sex:"Female", name:"Megan"},
{sex:"Male", name:"Taylor"},
{sex:"Female", name:"Madison"}
];
const transformed = people.reduce((acc, e) => {
Object.keys(e).forEach((k) => {
if (!acc[k]) acc[k] = [];
if (!acc[k].includes(e[k])) acc[k].push(e[k]);
});
return acc;
}, {});
console.log(transformed);
If for one of the object keys (sex or name in this case) a value array does not exist, it is created. Before a value is pushed into any of the value arrays, it is verified that it is not already present in that array.

compare and store string value by array in Javascript / node js

I fetched data from database so its coming in string format and I want to check this string with my array data
my string values come like
fish.jpg
animal.jpg
fish.pdf
animal.pdf
mammal_bio.pdf
fish_bio.jpg
fruit_bio.pdf
I want to compare this data with my array which contain
["mammal_bio.pdf","fruit_bio.pdf","animal_bio.pdf","tree_bio.pdf"]
So i want to compare all the array values which contain _bio.pdf and store them
matchedArray=["mammal_bio.pdf","fruit_bio.pdf"
unmatchedArray=["animal_bio.pdf","tree_bio.pdf"]
Don't use filter but forEach or for loop instead because you don't need to loop through all items again to get the two arrays.
const input = `fish.jpg
animal.jpg
fish.pdf
animal.pdf
mammal_bio.pdf
animal_bio.pdf
fish_bio.jpg
tree_bio.pdf
fruit_bio.pdf`;
check = ["mammal_bio.pdf", "fruit_bio.pdf", "animal_bio.pdf", "tree_bio.pdf"];
const matched = [];
const unmatched = [];
input
.split("\n")
.forEach(item =>
check.slice(0, 2).includes(item)
? matched.push(item)
: check.slice(-2).includes(item)
? unmatched.push(item)
: null
);
console.log({ matched });
console.log({ unmatched });
First you can filter out the strings which endsWith _bio.pdf.
Then for matched result filter with fiterArr and similarly for unmatched result
let filterArr = ['mammal_bio.pdf','fruit_bio.pdf'];
let bioArr = arr.filter(a => a.endsWith('_bio.pdf'));
let matched = bioArr.filter(b => filterArr.includes(b));
let unmatched = bioArr.filter(b => !filterArr.includes(b));
Just use
Array.filter
method.
If you return true the item will be inside the new Array, false excludes the item.
const noBioList = []
const bioList = list.filter(item => {
if (item.includes('_bio.pdf') {
return true
} else {
noBioList.push(item)
return false
}
}
console.log(bioList)
console.log(noBioList)
const input = `fish.jpg
animal.jpg
fish.pdf
animal.pdf
mammal_bio.pdf
animal_bio.pdf
fish_bio.jpg
tree_bio.pdf
fruit_bio.pdf`;
const inputList = input.split(/\n\s*/g)
const check = ["mammal_bio.pdf", "fruit_bio.pdf"];
const { matched, unmatched } = inputList.reduce((result, file) => {
if(/_bio\.pdf/.match(file)) {
if(check.indexOf(file) < 0) result.unmatched.push(file);
else result.matched.push(file)
}
return result
}, {
matched: [],
unmatched: []
})

Sort array elements on JavaScript

I have an array, each subarray of which contains different positions in different order:
[
["apple(2)", "banana(5)"],
["peach(3)", "banana(1)"],
["apple(1)"]
]
I need to sort it on JavaScript (ES6) and i expect to get an array like this:
[
["apple(2)", "banana(5)", "peach(0)"],
["apple(0)", "banana(1)", "peach(3)"],
["apple(1)", "banana(0)", "peach(0)"]
]
Order of each subarray should be the same. If subarray don't have some position, i need to add it with 0 value. Can i using something like map() or sort() function or need to compare it manually?
Here is functional programming approach, using a Map and reduce:
const data = [['apple(2)', 'banana(5)'],['peach(3)', 'banana(1)'],['apple(1)'],];
// Create a Map with default values for each name, i.e. with "(0)":
let names = new Map(data.flat().map(item => [item.replace(/\d+/, ""), item.replace(/\d+/, "0")]));
let result = data.map(row =>
[...row.reduce((map, item) =>
map.set(item.replace(/\d+/, ""), item), // Overwrite default
new Map(names) // Start with clone of original Map
).values()]
);
console.log(result);
You have to loop over to get the keys used. You then have to loop over a second time to get the fill in the missing keys. There are many ways of doing it, this is one.
var data = [
["apple(2)", "banana(5)"],
["peach(3)", "banana(1)"],
["apple(1)"]
];
// match string and number
var re = /([^(]+)\((\d+)\)/;
// Loop over and find all of the keys
var grouped = data.reduce((info, subset, index) => {
subset.forEach(item => {
// find the key and count
var parts = item.match(re);
// have we seen this key?
if (!info[parts[1]]) {
// if not create an array
info[parts[1]] = Array(data.length).fill(0);
}
// set the key index with the count
info[parts[1]][index] = parts[2];
})
return info;
}, {});
// loop over the groups and fill in the set
Object.entries(grouped).forEach(([key, counts], colIndex) => {
counts
.forEach((cnt, rowIndex) => {
data[rowIndex][colIndex] = `${key}(${cnt})`;
})
});
console.log(data);
First get the unique words. Then traverse array of arrays to check if the word is present or not. If it is not present then make the word according to your condition and if present then put the original word to the tmp array. At last sort it for each iteration. By the way, I used regex replace method to get the word.
const data = [
['apple(2)', 'banana(5)'],
['peach(3)', 'banana(1)'],
['apple(1)'],
];
const words = [...new Set(data.flat().map((x) => x.replace(/[^a-z]/gi, '')))];
const ret = data.map((x) => {
const tmp = [];
const newX = x.map((y) => y.replace(/[^a-z]/gi, ''));
for (let i = 0, l = words.length; i < l; i += 1) {
if (newX.includes(words[i])) tmp.push(x.shift());
else tmp.push(`${words[i]}(0)`);
}
return tmp.sort();
});
console.log(ret);

Java script filter on array of objects and push result's one element to another array

I have a array called data inside that array I have objects.
An object structure is like this
{
id:1,
especial_id:34,
restaurant_item:{id:1,restaurant:{res_name:'KFC'}}
}
I want to pass a res_name eg:- KFC
I want an output as a array which consists all the especial_ids
like this
myarr = [12,23,23]
I could do something like this for that. But I want to know what is more elegant way to do this.
const data = [
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'McDonalds'}},
{id:1,especial_id:8,restaurant_items:{id:5,res_name:'Kfc'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Sunmeal'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Kfc'}},
];
let temp = data.filter(element => element.restaurant_items.res_name == 'kfc')
let myArr = [];
temp.forEach(element=> myArr.push(element.especial_id));
console.log(myArr)//[8,6]
You can try this. It uses "Array.filter" and "Array.map"
var data = [
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'McDonalds'}},
{id:1,especial_id:8,restaurant_items:{id:5,res_name:'Kfc'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Sunmeal'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Kfc'}},
];
function getEspecialIdsByName(name) {
return data.filter(d => d.restaurant_items.res_name.toLowerCase() == name.toLowerCase())
.map(d => d.especial_id)
}
console.log(getEspecialIdsByName('Kfc'))
console.log(getEspecialIdsByName('Sunmeal'))
You can reduce to push elements which pass the test to the accumulator array in a single iteration over the input:
const data = [
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'McDonalds'}},
{id:1,especial_id:8,restaurant_items:{id:5,res_name:'Kfc'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Sunmeal'}},
{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Kfc'}},
];
console.log(
data.reduce((a, { especial_id, restaurant_items: { res_name }}) => {
if (res_name === 'Kfc') a.push(especial_id)
return a;
}, [])
);
Use Array.reduce
const data = [{id:1,especial_id:6,restaurant_items:{id:5,res_name:'McDonalds'}},{id:1,especial_id:8,restaurant_items:{id:5,res_name:'Kfc'}},{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Sunmeal'}},{id:1,especial_id:6,restaurant_items:{id:5,res_name:'Kfc'}}];
let result = data.reduce((a,c) => {
if(c.restaurant_items.res_name === 'Kfc') a.push(c.especial_id);
return a;
},[]);
console.log(result);

Filter an array of objects to only have the last occurrence of that object with the same certain property

How would you filter an array of objects to only have the last occurrence of that object with the same prop of foo? I.e
given:
[
{foo:1,id:1},
{foo:1,id:2},
{foo:2,id:3}
]
I want this back:
[
{foo:1,id:2},
{foo:2,id:3}
I'm using es6 so I can start from here:
this.data.filter((item,index,self)=> {
return self.findIndex(o => o.foo === item.foo);
})
var index = {};
var data = [{foo:1,id:1},{foo:1,id:2},{foo:2,id:3}];
data.forEach(item => index[item.foo] = item);
index[1];
// {foo:1,id:2}
Object.values(index)
// [{foo:1,id:2},{foo:2,id:3}]
Create a map by foo's value
var map = {};
var arr = [
{foo:1,id:1},
{foo:1,id:2},
{foo:2,id:3}
];
arr.forEach( function(item){
map[ item.foo ] = item;
});
and now finally just get the map's values
var finalArray = Object.keys( map ).map( function(key){
return map[key];
});
var arr = [{foo:1, id:1}, {foo:1, id:2}, {foo:2, id:3}, {foo:2, id:4}, {foo:2, id:5}, {foo:3, id:6}],
e = {};
arr.forEach(v => e[v.foo] = v.id);
var res = Object.keys(e).map(v => arr.find(c => c.id == e[v]));
console.log(res);
In just O(n) time you can achieve this job by the .rightReduce()
functionality with an initial value tuple holding both the result and a hash.
function lastWithProp(a,p){
return a.reduceRight((r,o) => r[1][p+o[p]] ? r : (r[1][p+o[p]] = true, r[0].push(o),r), [[],{}])[0];
}
var data = [{foo:1,id:1},{foo:1,id:2},{foo:2,id:3}],
result = lastWithProp(data,"foo");
console.log(result);
The .rightReduce() initial value (the r argument of the callback) is a tuple (a double/triple/quadruple... group of different type of data zipped together) like [[],{}] in this case. r[0] holds the result as it forms through the iterations of .rightReduce() and r[1] holds a hash map of the met objects property value keystring if never met before. So the first time we meet {foo:1,...} we mark it in the hash (r[1]) like "foo1" = true (r[1][p+o[p]] = true). So on...

Categories

Resources