Javascript : Concatenate object values in a variable - javascript

I'm trying to concatenate values from "seller" Key in a new variables "sellerList" but I'm not achieving to find a good solution.
const data = {
page: {},
product: {
attributes: {
condition: 'used',
offer: {
offer1: {
condition: 'used',
offerID: '1111',
seller: 'Ben',
sellerID: 'abc',
},
offer2: {
condition: 'used',
offerID: '2222',
seller: 'manu',
sellerID: 'def',
},
offer3: {
condition: 'used',
offerID: '3333',
seller: 'Ben',
sellerID: 'abc',
},
},
},
},
};
I found this post which has a similar issue, but it's not working on my side
As we can't use map method on object, I pushed my object into an array like this:
dataArr = [];
dataArr.push(data);
Then I used the following code to concatenate:
const sellersList = Object.keys(digitalData)
.map((o) => o.seller)
.join(';');
console.log('Offer list :' + sellersList);
But this returns an empty string: "Offer list :;"
So my goal is to have a final string like this : "ben;manu;ben"
Does anyone have an idea how to arrange the code fit with my case ?
Thank you for your help and your time.

Based on the data shape that you shared, you can do it like that:
Object.values(data.product.attributes.offer)
.map(offer => offer.seller)
.join(';')

You can do it like this. It does rely on your data having this specific shape with those precise key names - but it's not clear what else you can do as I don't know the details of where your data comes from and what else it might look like. Hope this helps give you a start, anyway!
const data = {
page: {},
product: {
attributes: {
condition: "used",
offer: {
offer1: {
condition: "used",
offerID: "1111",
seller: "Ben",
sellerID: "abc",
},
offer2: {
condition: "used",
offerID: "2222",
seller: "manu",
sellerID: "def",
},
offer3: {
condition: "used",
offerID: "3333",
seller: "Ben",
sellerID: "abc",
},
},
},
},
};
const result = Object.values(data.product.attributes.offer).map(offer => offer.seller).join(";");
console.log(result);

Related

JavaScript mapping and filtering on nested arrays

I'm guessing this is a basic question for anyone with experience and a logical brain, but this has stumped me for two days.
I'm trying to filter an array by states, then map just one property of the resulting array(s).
Here is my states array, which contains a subset of U.S. states:
const states = [{ state: 'AL' }, { state: 'OH' }, { state: 'PA' }]
Here is the array I want to first filter by state, and then map into a new array of just the values I need.
refData = [
{
state: 'AL',
details: [
{
code: '1A',
description: 'AL Description 1'
},
{
code: '1B',
description: 'AL Description 2'
},
{
code: '1C',
description: 'AL Description 3'
}
]
},
{
state: 'PA',
details: [
{
code: '1A',
description: 'PA Description 1'
},
{
code: '1B',
description: 'PA Description 2'
}
]
}
]
Here is my only working attempt to filter and then map, but it doesn't give me what I need:
const filteredRefData = refData
.filter((item) => (states.some(stateName => item.state === stateName.state)))
.map((item) => item.details)
What this gets me is an array of ALL the details, both code and description. What I need is JUST the description value, but no matter what I try, I can't arrive at that end result.
What I get from this map:
[
0: [
0: {code: "1A", description: "AL Description 1"}
1: {code: "1B", description: "AL Description 2"}
2: {code: "1C", description: "AL Description 3"}
],
1: [
0: {code: "1A", description: "PA Description 1"}
1: {code: "1B", description: "PA Description 2"}
]
]
What I need from this map:
[
0: [
0: "AL Description 1"
1: "AL Description 2"
2: "AL Description 3"
],
1: [
0: "PA Description 1"
1: "PA Description 2"
]
]
I tried using dynamic indexes, but that failed because any index I passed always related to the top level array, and not the nested array. I also tried the reduce method, but I found it difficult to understand how reduce works with just an object's key/value pairs.
Thank you for any help you can provide!
You were almost there. The only change needed was, in the final .map, not to just return item.details but the result of map-ing that array to extract just the description:
const states = [{ state: 'AL' }, { state: 'OH' }, { state: 'PA' }];
const refData = [
{
state: 'AL',
details: [
{
code: '1A',
description: 'AL Description 1'
},
{
code: '1B',
description: 'AL Description 2'
},
{
code: '1C',
description: 'AL Description 3'
}
]
},
{
state: 'PA',
details: [
{
code: '1A',
description: 'PA Description 1'
},
{
code: '1B',
description: 'PA Description 2'
}
]
}
];
const filteredRefData = refData
.filter((item) => (states.some(stateName => item.state === stateName.state)))
.map((item) => item.details.map(({ description }) => description));
console.log(filteredRefData);
You are right that this is a job for reduce: a map operation will yield a 1:1 translation of the input array (e.g. refData.map(state => state.state) would return an array of the same length containing only the state attribute), whereas reduce can return an array with more or fewer results.
In your case, you start with x number of states, but you will return y descriptions, so map is not an option, you must use reduce (and this is a good example of how to use a functional approach).
For example, if you wanted to strip out just the state abbreviation using reduce instead of map, you could do that by accumulating the state abbreviation:
data.reduce(function(acc, x) {
return acc.concat(x.state);
}, []);
Here we set the initial value of the accumulator to an empty array [] (2nd arg) and we use concat to append single values to the end of the acc array -- the result is the same as using map.
In your case, you want to concatenate an array of descriptions (or some other variable attribute), so here's how you could reduce the descriptions:
var refData = [
{
state: 'AL',
details: [
{
code: '1A',
description: 'AL Description 1'
},
{
code: '1B',
description: 'AL Description 2'
},
{
code: '1C',
description: 'AL Description 3'
}
]
},
{
state: 'PA',
details: [
{
code: '1A',
description: 'PA Description 1'
},
{
code: '1B',
description: 'PA Description 2'
}
]
}
];
refData.reduce(function(acc, x) {
var descriptions = x.details.map(function(detail) {
return detail.description;
});
return acc.concat(descriptions);
}, []);
or more tersely as
refData.reduce(function(acc, x) {
return acc.concat(x.details.map(detail => detail.description));
}, []);
If you insist on using only filter and map, try this:
const filteredRefData = refData
.filter((item) => (states.some(stateName => item.state === stateName.state)))
.map((item) => item.details.map(d => d.description))
But that's not really optimal solution. Maybe try using reduce instead and compare results.
I guess consuming the 'description' field would solve your problem. Try this:
const filteredRefData = refData
.filter((item) => (states.some(stateName => item.state === stateName.state)))
.map((item) => item.details.description)

Trying to filter an array of objects that has a property value that is also an array

I have this object inside a json:
{
"group": "A",
"id": "50"
"person": [
{
"name": 'Joe',
"age": '29'
"hobbies": ["Watching movies", "Gaming"]
},
{
"name": 'Jessie',
"age": '27'
"hobbies": ["Gaming", "Reading"]
}
]
}
I want to filter the people by their hobbies. For example, if I filter by Gaming I need to create an array of objects with Joe and Jessie. If I filter by Reading, then the array would only have Jessie.
Here is my code:
import { people } from '../../../data/index' // this is the json I shower above
let filteredArray;
filteredArray = people.filter(person => {
return person.hobbies == "Gaming";
})
this doesn't work, but if change the hobbies to a single word on the json, like this:
{
"name": 'Jessie',
"age": '27'
"hobbies": "Gaming"
}
then it work just fine.
So is there a way to use filter with a array of hobbies to check if one of the values match my condition?
I'm using only vanilla Js and I only want to support chrome.
Sorry for any english mistake or if the question is not clear enought, I'm still in the beggining of my studies
You have to use includes method. Because you are trying to search in array:
const filteredArray = people.filter(person => {
return person.hobbies.includes("Gaming");
})
const data = {
group: 'A',
id: '50',
person: [
{
name: 'Joe',
age: '29',
hobbies: ['Watching movies', 'Gaming']
},
{
name: 'Jessie',
age: '27',
hobbies: ['Gaming', 'Reading']
}
]
};
const result = data.person.filter(el => el.hobbies.includes('Gaming'));
console.log(result);

How can I prevent duplicate keys when adding data to an object array?

I have some code where I am looping through some records in a table, and whilst doing this I'm organising this data into a JavaScript object array.
For example the data below.
I need to ensure that if a record "Name" has already been recorded, then rather than create a new item it uses the existing item so that the end result will be an object or array like this:
{
"bobjones": {
"sessions": 7
},
"annfrank": {
"sessions": 4
},
"fredsmith": {
"sessions": 4
}
}
Doing this in PHP is easy, but I'm struggling with this in JS due to the way keys are interpreted. Could somebody provide some direction?
const inputData = [
{ name: 'Bob Jones', date: '----', session: 1 },
{ name: 'Ann Frank', date: '----', session: 1 },
{ name: 'Bob Jones', date: '----', session: 1 },
{ name: 'Fred Smith', date: '----', session: 1 },
]
var outputData = {}
for(let doc of inputData) {
if(outputData[doc.name]) {
outputData[doc.name].session = outputData[doc.name].session + doc.session
} else {
outputData[doc.name] = doc
}
}
console.log(outputData)
Now outputData is:
{ 'Bob Jones': { name: 'Bob Jones', date: '----', session: 2 },
'Ann Frank': { name: 'Ann Frank', date: '----', session: 1 },
'Fred Smith': { name: 'Fred Smith', date: '----', session: 1 } }
You can just test to see if the object property exists. If so, add to its sessions property, if not, set it.
if(obj[prop]) {
obj[prop].sessions += sessions;
} else {
obj[prop] = { sessions };
}
In the first if statement, if you're concerned that obj[prop] may exist but obj[prop].sessions may not, you can change it to if(obj[prop] && obj[prop].sessions) { ... }
You could use the reduce method, assuming that you input data is an array of objects (since, that is generally how you get data when consulting a database).
const table = [
{name: "Bob Jones", date: "12-12-2019", sessions: 3},
{name: "Ann Frank", date: "12-9-2019", sessions: 4},
{name: "Bob Jones", date: "12-9-2019", sessions: 2},
{name: "Fred Smith", date: "12-9-2019", sessions: 4}
];
let res = table.reduce((res, {name, date, sessions}) =>
{
if (res[[name]])
res[[name]].sessions += sessions;
else
res[[name]] = {sessions: sessions};
return res;
}, {});
console.log(res);

how to remove an element from a list typescript

Im using Angular 6, I have list and Im exporting it to CSV file using Angular5-csv, I want to remove the last column of the list i.e., the last element of each array in the list. my list looks like
let traceslist = [
{
"name": "abcd",
"email": "abcd#example.com",
"decision": "yes",
"userid": "abcd"
},
{
"name": "phill";
"email": "abcd#example.com";
"decision": "yes";
"userid": "phill";
},
{
"name": "raj";
"email": "raj#example.com";
"decision": "no";
"userid": "raj";
},
{
"name": "john";
"email": "john#example.com";
"decision": "yes";
"userid": "john";
}
]
now, I want to remove the elements userid, so that the column will not be present in my csv file, from the list. I have tried using splice but that was not successful.
It'd be great if anyone of you can help me with this.
Use the .map array method to remove the userid from every item in your array.
traceslist = traceslist.map(item => {
delete item.userid;
return item;
});
By the way, it's not angular related so your title and tag is a little misleading. An array is the same in pure javascript.
You can't use delete to remove an item from an array. This is only used to remove a property from an object.
You should use splice to remove an element from an array:
deleteMsg(removeElement:string) {
const index: number = traceslist.indexOf(removeElement);
if (index !== -1) {
traceslist.splice(index, 1);
}
}
This is a simple javascript problem. Also you need to convert your data to string.
See the example below:
let traceslist = [
{
'name': 'abcd',
'email': 'abcd#example.com',
'decision': 'yes',
'userid': 'abcd'
},
{
'name': 'abcd',
'email': 'abcd#example.com',
'decision': 'yes',
'userid': 'abcd'
}
];
traceslist.forEach( item => delete item.userid );
console.log(traceslist);
We can use .map() method to achieve this
let traceslist = [
{
name: 'abcd',
email: 'abcd#example.com',
decision: 'yes',
userid: 'abcd',
},
{
name: 'abcd',
email: 'abcd#example.com',
decision: 'yes',
userid: 'abcd',
},
{
name: 'abcd',
email: 'abcd#example.com',
decision: 'yes',
userid: 'abcd',
},
{
name: 'abcd',
email: 'abcd#example.com',
decision: 'yes',
userid: 'abcd',
}
]
const result = traceslist.map(o => {
delete o.userid;
return o;
})
console.log(result);
First of all, your JSON format is wrong, semicolon (;) is first and the strings should be in quotes check it below
let obj = [{
name: "abcd",
email: "abcd#example.com",
decision: "yes",
userid: "abcd",
},
{
name: "abcd",
email: "abcd#example.com",
decision: "yes",
userid: "abcd",
},
{
name: "raj",
email: "raj#example.com",
decision: "no",
userid: "raj",
},
{
name: "john",
email: "john#example.com",
decision: "yes",
userid: "john",
}
]
let filtered = obj.map(item => {
delete item.userid;
return item;
});
console.log(filtered);

Lodash: Swap key with value objects internal attribute

I am getting below JSON response:
users: {
1: {
name: "John",
email: "john#test.com",
id: 1,
place: "NY"
},
2: {
name: "Alex",
email: "alex#test.com",
id: 2,
place: "FL"
},
3: {
name: "Tony",
email: "tony#test.com",
id: 3,
place: "TX"
}
.
.
.
.
.
.
}
I want to swap the id key with email key from the inner object value as below format.
users: {
"john#test.com": {
name: "John",
email: "john#test.com",
id: 1,
place: "NY"
},
}
I am using below lodash code to make it work and its working fine:
_.keyBy(_.values(data), 'email');
Is there a better way I can handle it with lodash? I am new to lodash and I wanted to understand whether the code can be refactored further.
See _.keyBy() accepts a collection (an array or an object), you can skip the _.values() call:
const users = {"1":{"name":"John","email":"john#test.com","id":1,"place":"NY"},"2":{"name":"Alex","email":"alex#test.com","id":2,"place":"FL"},"3":{"name":"Tony","email":"tony#test.com","id":3,"place":"TX"}};
const result = _.keyBy(users, 'email');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
If you are looking for Vanilla JavaScript solution you can use array#reduce like this:
users = {
1: {
name: "John",
email: "john#test.com",
id: 1,
place: "NY"
},
2: {
name: "Alex",
email: "alex#test.com",
id: 2,
place: "FL"
},
3: {
name: "Tony",
email: "tony#test.com",
id: 3,
place: "TX"
}
}
let newUsers = Object.keys(users).reduce((obj, key) => {
obj[users[key].email] = users[key];
return obj;
}, {});
console.log(newUsers);

Categories