I'm trying to convert array of objects to comma separated string array.
Input:
report: [{"name":"abc","age":23,"gender":"male"},
{"name":"def","age":24,"gender":"female"},
{"name":"ghi","age":25,"gender":"other"}]
Expected Output:
[["abc",23,"male"],["def",24,"female"],["ghi",25,"other"]]
Code:
resultArray: any = [];
report.forEach(d => {
var energy = Object.values(d).join(",");
this.resultArray.push([energy]);
});
Result: [["abc,23,male"],["def,24,female"],["ghi,25,other"]]
Where am i wrong?
join(',') will join array separated by , and you are assigning it in array as:
this.resultArray.push([energy]);
All you have to do is:
var energy = Object.values(d); // get all the values of an object
this.resultArray.push(energy); // Pust energy values in resultArray
const report = [
{ name: 'abc', age: 23, gender: 'male' },
{ name: 'def', age: 24, gender: 'female' },
{ name: 'ghi', age: 25, gender: 'other' },
];
const resultArray = [];
report.forEach((d) => {
var energy = Object.values(d);
resultArray.push(energy);
});
console.log(resultArray);
With .join(','), you're turning each object you're iterating over into a single string. If you want 3 separate elements, don't join.
const report = [{"name":"abc","age":23,"gender":"male"},
{"name":"def","age":24,"gender":"female"},
{"name":"ghi","age":25,"gender":"other"}]
const resultArray = [];
report.forEach(d => {
var energy = Object.values(d);
resultArray.push(energy);
});
console.log(resultArray);
Or, better:
const report = [{"name":"abc","age":23,"gender":"male"},
{"name":"def","age":24,"gender":"female"},
{"name":"ghi","age":25,"gender":"other"}]
const resultArray = report.map(Object.values);
console.log(resultArray);
Related
I have a long array of objects. I want to write a function to find for example names that start with specific letter and end with another specific letter and return a list of names that starts and end with them.
I tried some solutions but did not get answer.
Here I use a simple list: and I want a list that name start with "A" and end with "i" or any other case
myList = [{name: "Aji",family: "Ziansi"}, { name: "Alex", family: "ortega"}, {name:"Amandi",family: "Sedirini"}];
Output should be like this:
desiredLiset = [{name: "Aji",family: "Ziansi"}, {name:"Amandi",family: "Sedirini"}];
just in function declaration method.
Any solutions would be appreciated.
We can use Array.filter()
const myList = [{
name: "Aji",
family: "Ziansi"
}, {
name: "Alex",
family: "ortega"
}, {
name: "Amandi",
family: "Sedirini"
}];
const filterList = (list, start, end) => {
return list.filter(obj => {
const name = obj.name;
return name[0] === start && name[name.length - 1] === end;
});
};
const filtered = filterList(myList, "A", "i");
console.log(filtered);
You can use .filter() to get a list of the names you want:
myList = [{name: "Aji",family: "Ziansi"}, { name: "Alex", family: "ortega"}, {name:"Amandi",family: "Sedirini"}];
let desiredLiset = myList.filter(function(n){
return n.name.match(/^A.*i$/i) // Names that begin with 'A' and end with 'i'
});
console.log(desiredLiset)
// 0: Object { name: "Aji", family: "Ziansi" }
// 1: Object { name: "Amandi", family: "Sedirini" }
Try this:
myList = [{name: "Aji",family: "Ziansi"}, { name: "Alex", family: "ortega"}, {name:"Amandi",family: "Sedirini"}];
const start='A'
const end='i'
const startEndRE = new RegExp(`^${start}.*${end}$`)
myList.filter(item=>(
startEndRE.test(item.name)
))
// Result
// [
// { name: 'Aji', family: 'Ziansi' },
// { name: 'Amandi', family: 'Sedirini' }
// ]
It is also possible to do using endsWith() and startsWith()
try:
const myList = [{ name: "Aji", family: "Ziansi" }, { name: "Alex", family: "ortega" }, { name: "Amandi", family: "Sedirini" }];
const newlist = myList.filter((obj) => obj.name.startsWith('A') && obj.name.endsWith('i'));
console.log(newlist);
I havve two different arrays with different property names like below
arrayA = [
{ id: 20, name: 'Jason' },
{ id: 15, name: 'Harry' },
{ id: 5, name: 'Clara' },
{ id: 9, name: 'Melonie' }
]
arrayB = [
{ courseID: 12, studentID: 20 },
{ courseID: 12, studentID: 15 }
]
I want to compare these two different arrays and remove unmatched ids from arrayA. For comparison, id field of arrayA and studentID field of arrayB matters. if these fileds aren't equal to each other, they should be removed from arrayA.
Expected is below
arrayA = [{id: 20, name: 'Jason' }, { id: 15, name: 'Harry' }]
Here is what I tried below but didn't work. Gave me empty array.
filteredElements = this.arrayA.map(e => e.id).filter(
val => this.arrayB.indexOf(val.studentID) !== -1
);
You can do that in following steps:
Use map() on arrayB and create array of courseID.
Then create a Set() from that Array
Then use filter() arrayA and check whether id of object exists in above created Set or not using Set.prototype.has()
const arrayA = [{id:20,name:'Jason'},{id:15,name:'Harry'},{id:5,name:'Clara'},{id:9,name:'Melonie'}]
const arrayB =[{courseID:12,studentID:20},{courseID:12,studentID:15}];
const ids = new Set(arrayB.map(x => x.studentID));
const res = arrayA.filter(x => ids.has(x.id));
console.log(res);
let arrayA = [{id: 20,name: 'Jason'},{id: 15,name: 'Harry'},{id: 5,name: 'Clara'},{id: 9,name: 'Melonie'}]
let arrayB = [{courseID: 12,studentID: 20},{courseID: 12,studentID: 15}];
let filtered=arrayA.filter(obj =>{ if(arrayB.find(course => course.studentID == obj.id))return true;return false;
});
console.log(filtered);
Try this:
var studentIds = arrayB.map(course => course.studentID);
var result = arrayA.filter(student => studentIds.includes(student.id));
The variable result contains your result.
Create a dictionary from courseMembers, keyed on studentID, to enable O(1) lookup.
Filter students according to the dictionary.
const students = [{id:20,name:'Jason'},{id:15,name:'Harry'},{id:5,name:'Clara'},{id:9,name:'Melonie'}]
const courseMembers = [{courseID:12,studentID:20},{courseID:12,studentID:15}]
function withCourses(students, courseMembers) {
const map = courseMembers.reduce((acc, {studentID}) =>
(acc[studentID] = true, acc), {})
return students.filter(({id}) => map[id])
}
const result = withCourses(students, courseMembers)
console.log(result) // [{ id:20, name:"Jason" },{ id:15, name:"Harry" }]
Consider, I have the following two arrays of objects:
const existingAndArchivedBookings =
[
{"booking_id":-2},
{"booking_id":-1},
{"booking_id":999}
]
const newAndExistingBookings =
[
{bookingId:-2, name: "name1"},
{bookingId:-3, name: "name1"},
{bookingId:-1, name: "namex"}
]
What I want to do is determine which of the bookings in the second array are new and which are existing. Any bookingId that is in both arrays is existing. Any bookingID that is in the second array but not the first is new. So, the result of the solution should be an array as follows:
[ { bookingId: -2, existing: true, name: 'name1' },
{ bookingId: -3, existing: false, name: 'name1' },
{ bookingId: -1, existing: true, name: 'namex' } ]
I have a solution (which I'll post as an answer), but I think there's probably a more efficient way of doing it. Good luck.
If you want a non-R answer: you can use a simple map to iterate over the data, compare the booking ids in both arrays (with some), and return a new array of objects.
const existingAndArchivedBookings = [{booking_id:-2},{booking_id:-1},{booking_id:999}];
const newAndExistingBookings = [{bookingId:-2, name: "name1"},{bookingId:-3, name: "name1"},{bookingId:-1, name: "namex"}];
function testBookings(arr1, arr2) {
return arr2.map(({ bookingId, name }) => {
const existing = arr1.some(obj => obj.booking_id === bookingId);
return { bookingId, existing, name };
});
}
const out = testBookings(existingAndArchivedBookings, newAndExistingBookings);
console.log(out);
You can greatly simplify it using Array.prototype.reduce to form the result of the comparisons between the 2 arrays and Array.prototype.findIndex to test whether the object in the second array is present in the first array:
const existingAndArchivedBookings =
[
{"booking_id":-2},
{"booking_id":-1},
{"booking_id":999}
]
const newAndExistingBookings =
[
{bookingId:-2, name: "name1"},
{bookingId:-3, name: "name1"},
{bookingId:-1, name: "namex"}
]
const res = newAndExistingBookings.reduce((acc, ele) => {
const idx = existingAndArchivedBookings.findIndex(b => b.booking_id === ele.bookingId);
let existing = false;
if(idx >=0 ){
existing = true;
}
return acc.concat({bookingId : `${ele.bookingId}`, existing: `${existing}`, name: `${ele.name}`});
}, []);
console.log(res);
Here's what I came up with, which seems a bit long winded
const R = require('ramda')
const existingAndArchivedBookings = [{"booking_id":-2},{"booking_id":-1},{"booking_id":999}]
const newAndExistingBookings = [{bookingId:-2, name: "name1"}, {bookingId:-3, name: "name1"}, {bookingId:-1, name: "namex"}]
const existingAndArchivedKeys = existingAndArchivedBookings.map(value => value.booking_id)
const newAndExistingKeys = newAndExistingBookings.map(value => value.bookingId)
const existingKeys = existingAndArchivedKeys.filter(key => newAndExistingKeys.includes(key))
const newKeys = newAndExistingKeys.filter(key => !existingAndArchivedKeys.includes(key))
const existingBookingIds = existingKeys.map(key => {
return {bookingId: key, existing: true}
})
const newBookingIds = newKeys.map(key => {
return {bookingId: key, existing: false}
})
const allArray = R.concat(newAndExistingBookings, R.concat(existingBookingIds, newBookingIds))
console.log(R.values(R.reduceBy(R.mergeLeft, {}, R.prop('bookingId'), allArray)))
I need help transforming an array of objects using ramda; I'd like to
group by a specified property
sum another property on the
resulting set
given an array like this:
var arr = [
{
title: "scotty",
age: 22,
score: 54,
hobby: "debugging"
}, {
title: "scotty",
age: 22,
score: 19,
hobby: "debugging"
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
if I want to group by title and sum on age it should return the following summary of values
var arr = [
{
title: "scotty",
age: 44,
hobby: "debugging",
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
when the unspecified property's differ in value they should be omitted, but if unspecified property's are the same in value it should remain in the final result.
** My Solution **
/*
* [Student]
*/
var arr = [
{
title: "scotty",
age: 22,
score: 54,
hobby: "debugging"
}, {
title: "scotty",
age: 22,
score: 19,
hobby: "debugging"
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
/*
* String -> [[Student]] -> [Student]
*/
var sumOnProperty = function(property, v){
var sum = (x,y) => x[property] + y[property];
var new_array = [];
v.forEach(arr => {
if(arr.length > 1){
arr[0]["age"] = arr.reduce(sum)
new_array.push(arr[0]);
} else {
if(arr.length != 0){
new_array.push(arr[0]);
}
}
})
return new_array;
}
/*
* String -> String -> [Student] -> [Student]
*/
var groupsumBy = function(groupproperty, sumproperty, arr){
// create grouping
var grouping = R.groupBy(R.prop(groupproperty), arr)
// convert grouping object to array
var result1 = R.valuesIn(grouping);
// sum each grouping and flatten 2d array
var result2 = sumOnProperty(sumproperty, result1);
return result2;
}
groupsumBy("title","age",arr);
To fix your groupBy problem you need to see that groupBy takes a key-generation function function and not a binary predicate.
So, for instance,
const byTitle = R.groupBy(R.prop('title'));
This should get you through your current block. If you need help with the summation, let me know.
Update:
You asked for my approach. It does differ from yours a fair bit. I would probably do something like this:
const sumBy = prop => vals => reduce(
(current, val) => evolve({[prop]: add(val[prop])}, current),
head(vals),
tail(vals)
)
const groupSumBy = curry((groupOn, sumOn, vals) =>
values(map(sumBy(sumOn))(groupBy(prop(groupOn), vals)))
)
groupSumBy('title', 'age', people)
Or if I wanted it a little more concise, I might switch to:
const sumBy = prop => lift(
reduce((current, val) => evolve({[prop]: add(val[prop])}, current)
))(head, tail)
Note that sumBy is relatively reusable. It's not perfect, because it would fail on an empty list. But in our case, we know that the output of groupBy will never create such an empty list for a key. And any version which didn't fail on an empty list would need a way to supply the default case. It simply gets ugly.
You can see this in action on the Ramda REPL.
You could probably make a more easily readable version of groupSumBy using pipe or compose if you were willing to call first with the groupOn and sumOn values, then call the resulting function with the values, that is, if the invocation looked like this:
groupSumBy('title', 'age')(people)
// or more likely:
const foo = groupSumBy('title', age)
foo(people)
But I leave that as an exercise for the reader.
using ramda group by property and sum results on specified property
One option is to reduceBy as follows:
import * as R from "ramda";
const arr = [
{
title: "scotty",
age: 22,
score: 54,
hobby: "debugging"
}, {
title: "scotty",
age: 22,
score: 19,
hobby: "debugging"
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
const reduction =
R.reduceBy((acc, next) => acc + next.age, 0, (x) => x.title, arr);
console.log(JSON.stringify(reduction, undefined, 2));
The output has grouped by title and has summed the age.
{
"scotty": 44,
"gabriel": 40
}
I have severel Objects containing one sort of data:
Prices:
'btc-usd' : 2640, 'ltc-usd': 40, ...
Amount of Crypto:
'btc-usd': 2.533, 'ltc-usd': 10.42, ...
How can I take these Objects and create an Array of Objects like:
[ { name: 'Bitcoin', amount: 2.533, value: 2640, id: 'btc-usd' },
{ name: 'Litecoin', amount: 10.42, value: 40, id: 'ltc-usd' }, ...
]
Thanks a lot for your help!
You could map the keys of one of the objects to produce a new array of objects. You just have to make sure, that the key is in every of these objects.
const names = {
'btc-usd' : 'Bitcoin',
'ltc-usd': 'Litecoin',
...
}
const prices = {
'btc-usd' : 2640,
'ltc-usd': 40,
...
}
const amounts = {
'btc-usd': 2.533,
'ltc-usd': 10.42,
...
}
const cryptos = Object.keys(names).map((key, index) => ({
name: names[key],
amount: amounts[key] ,
value: prices[key]},
id: key
}));
You could use a hash map (e.g. 'btc-usd' => {name:"Bitcoin",...}) to create new objects. This hashmap can be easily converted to an array.
var input={
value:{'btc-usd' : 2640, 'ltc-usd': 40},
amount:{'btc-usd': 2.533, 'ltc-usd': 10.42},
name:{"btc-usd":"Bitcoin","ltc-usd":"Litecoin"}
};
var hash={};
for(key in input){
var values=input[key];
for(id in values){
if(!hash[id]) hash[id]={id:id};
hash[id][key]=values[id];
}
}
var output=Object.values(hash);
http://jsbin.com/fadapafaca/edit?console
Here's a generalized function, add, that accepts a field name and an object of values and maps them into a result object which can then be mapped into an array.
const amounts = {btc: 123.45, eth: 123.45};
const names = {btc: 'Bitcoin', eth: 'Etherium'};
const result = {};
const add = (field, values) => {
Object.keys(values).forEach(key => {
// lazy initialize each object in the resultset
if (!result[key]) {
result[key] = {id: key};
}
// insert the data into the field for the key
result[key][field] = values[key];
});
}
add('amount', amounts);
add('name', names);
// converts the object of results to an array and logs it
console.log(Object.keys(result).map(key => result[key]));
const prices = {
'btc-usd' : 2640,
'ltc-usd': 40
};
const amounts = {
'btc-usd': 2.533,
'ltc-usd': 10.42
};
First, create a dictionary of what each abbreviation stands for.
const dictionary = {
'btc': 'Bitcoin',
'ltc': 'Litecoin'
};
Then, populate an empty array with objects containing the relevant information. In each of these objects, the name would correspond to the relevant key within the dictionary object. At the same time, the amount and value would correspond to the relevant key within the amounts and prices objects respectively. Finally, the Id would correspond to the key itself.
const money = [];
for(let coin in prices) {
money.push({
name: dictionary[coin.substr(0, coin.indexOf('-'))],
amount: amounts[coin],
value: prices[coin],
id: coin
});
}
console.log(money);