Related
I have a json file.
[
{
"line": 1,
"elements": [
{
"start_timestamp": "2022-10-17T20:07:41.706Z",
"steps": [
{
"result": {
"duration": 12216552000,
"status": "passed"
},
"line": 5,
"name": "m0e",
"match": {
"location": "seleniumgluecode.book.user_is_on_homepagee()"
},
"keyword": "Given "
},
{
"result": {
"duration": 2074982200,
"status": "passed"
},
"line": 6,
"name": "m1e1",
"match": {
"location": "seleniumgluecode.book.user_enters_Usernamee()"
},
"keyword": "When "
}
],
"tags": [
{
"name": "#Smokee"
}
]
},
{
"start_timestamp": "2022-10-17T20:08:12.284Z",
"steps": [
{
"result": {
"duration": 12090584100,
"status": "passed"
},
"line": 12,
"name": "m0e2",
"match": {
"location": "seleniumgluecode.book2.user_is_on_homepageee()"
},
"keyword": "Given "
}
],
"tags": [
{
"name": "#Smokee"
}
]
}
],
"name": "Login Featuree",
"description": " Verify if user is able to Login in to the sitee",
"id": "login-featuree",
"keyword": "Feature",
"uri": "file:src/test/java/features/tribe/squad1/kitab.feature",
"tags": []
},
{
"line": 1,
"elements": [
{
"start_timestamp": "2022-10-17T20:08:34.480Z",
"steps": [
{
"result": {
"duration": 11366098500,
"status": "passed"
},
"line": 5,
"name": "m0e",
"match": {
"location": "seleniumgluecode.book.user_is_on_homepagee()"
},
"keyword": "Given "
}
],
"tags": [
{
"name": "#Smokee"
}
]
}
],
"name": "Login Featureefghfgh",
"description": " Verify if user is able to Login in to the sitee",
"id": "login-featureefghfgh",
"keyword": "Feature",
"uri": "file:src/test/java/features/tribe1/squad2/kitab2.feature",
"tags": []
},
{
"line": 19,
"elements": [
{
"start_timestamp": "2022-10-17T20:09:40.836Z",
"steps": [
{
"result": {
"duration": 12761711100,
"status": "passed"
},
"line": 23,
"name": "m0e",
"match": {
"location": "seleniumgluecode.book.user_is_on_homepagee()"
},
"keyword": "Given "
}
],
"tags": [
{
"name": "#Smokee"
}
]
}
],
"name": "X Feature",
"description": " Verify if user is able to Login in to the sitee",
"id": "login-featuree",
"keyword": "Feature",
"uri": "file:src/test/java/features/tribe2/test.feature",
"tags": []
}
]
I am getting url addresses in this array
document.addEventListener("DOMContentLoaded", () => {
var i = report.length;
var array = [];
for(x = 0; x < i; x++){
array.push(report[x].uri.split("/"));
}
console.log(array2);
});
This return me :
0:
(7) ['file:src', 'test', 'java', 'features', 'tribe1', 'squad1', 'kitab.feature']
1:
(7) ['file:src', 'test', 'java', 'features', 'tribe1', 'squad2', 'kitab2.feature']
2:
(6) ['file:src', 'test', 'java', 'features', 'tribe2, kitab3.feature']
I don't need file:src, test, java, features. Deleting them in 3 arrays and getting a unique array like this:
0:
(3) ['tribe1', 'squad1', 'kitab.feature']
1:
(3) ['tribe1', 'squad2', 'kitab2.feature']
2:
(2) ['tribe2, kitab3.feature']
Finally, if there are 2 elements before the .feature, I need to create a new array by considering 1 as squad and 2 as tribe. Like this:
Diagram
[tribe1
squad1
elem
1
2
name
url
squad2
elem
1
2
name
url
tribe2
elem
1
2
name
url
]
How can I do that?. Thank you.
You should try destructing the array. An example is shown below:
[a,b,c,d, ...rest] = ['file:src', 'test', 'java', 'features', 'tribe1', 'squad1', 'kitab.feature']
console.log(rest);
You can transform or create a new array based on input array with this simple logic with the help of Array.map() along with String.split() and Array.splice() method.
Live Demo :
const arr = [
{
"line": 1,
"uri": "file:src/test/java/features/tribe/squad1/kitab.feature"
},
{
"line": 1,
"uri": "file:src/test/java/features/tribe1/squad2/kitab2.feature"
},
{
"line": 19,
"uri": "file:src/test/java/features/tribe2/test.feature"
}
];
const res = arr.map(({ uri}) => uri.split('/').splice(4));
console.log(res);
I've 2 different APIs. first one returns an array of event objects (this data set is growing and expected to be large). each event has a category array that has a list of strings. The other API returns an array of filter objects. each filter has a "name" property and an array of keywords. any keyword included in the categories array in any event should go under this filter name.
The ultimate goal is to have a list of filters on the screen and when a user click on a filter I should render all events under this filter.
Event Object Example:
{
"text": {
"headline": "Headline example",
"text": "event description "
},
"media": {
"url": "https://www.google.com/",
"caption": "",
"credit": ""
},
"categories": [
"National",
"Canada",
"British Columbia"
]
}
Filters Object Example:
{
"filters": [
{
"keywords": [
"Atlantic",
"New Brunswick",
"Newfoundland and Labrador",
"Prince Edward Island",
"Nova Scotia"
],
"name": "Atlantic"
},
{
"keywords": [
"ontario",
"Quebec"
],
"name": "Central Canada"
},
{
"keywords": [
"Manitoba",
"Saskatchewan",
"Alberta"
],
"name": "Prairie Provinces"
},
{
"keywords": [
"British Columbia"
],
"name": "West Coast"
},
{
"keywords": [
"Nunavut",
"Northwest Territories",
"Yukon Territory"
],
"name": "North"
},
{
"keywords": [
"National"
],
"name": "National"
}
]
}
After a couple of days working on it I came up with this solution.
function filterTimelineData(filtersObj, timelineData) {
if (!timelineData || !filtersObj) return [];
// create a new object with filters "name" as key;
const filters = Object.keys(filtersObj);
const filteredTimelineData = Object.keys(filtersObj).reduce((o, key) => ({ ...o, [key]: [] }), {});
const filteredData = timelineData.events.reduce((acc, current) => {
let filterMatch = false;
let filterMatchName = '';
for (let i = 0; i < filters.length; i++) {
filterMatch = current.categories.some(item => {
return filtersObj[filters[i]].includes(item.toLocaleLowerCase());
});
if (filterMatch && filterMatchName !== filters[i]) { // to avoid duplicated items with different categories under the same filter
filterMatchName = filters[i];
acc[filters[i]].push(current);
}
}
return acc;
}, filteredTimelineData);
return filteredData;
}
export function timelineFiltersObj(filters) {
const filtersObj = filters.filters.reduce((acc, current) => {
const filterName = current.name.replace(/ /g, '_').toLocaleLowerCase();
if (!acc.hasOwnProperty(filterName)) {
acc[filterName] = [];
}
acc[filterName] = [].concat(current.keywords.map(item => item.toLocaleLowerCase()));
return acc;
}, {});
return filtersObj;
}
Desired output:
An object or an array for all filters to be rendered on the screen
An object with filters name as a key and the value would be an array of events that has any keyword that matches any of this filter keywords
check this code example: link
My Questions:
Is there an easier/simpler way to solve this problem?
I'm passing "filteredTimelineData" object as initial value to .reduce function. Is this legitimate? I couldn't find any answers online to this question specifically.
from a time complexity prospective. will this code cause any memory issue if the dataset grows?
This is a simple way to get the above result. I am using JavaScript ES5 features in this solution which is supported by almost all the browsers except IE9
const filters = {
"filters": [
{
"keywords": [
"Atlantic",
"New Brunswick",
"Newfoundland and Labrador",
"Prince Edward Island",
"Nova Scotia"
],
"name": "Atlantic"
},
{
"keywords": [
"ontario",
"Quebec"
],
"name": "Central Canada"
},
{
"keywords": [
"Manitoba",
"Saskatchewan",
"Alberta"
],
"name": "Prairie Provinces"
},
{
"keywords": [
"British Columbia"
],
"name": "West Coast"
},
{
"keywords": [
"Nunavut",
"Northwest Territories",
"Yukon Territory"
],
"name": "North"
},
{
"keywords": [
"National"
],
"name": "National"
}
]
};
const timelineData = {
"events": [
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"New Brunswick"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"National"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": "https://youtu.be/poOO4GN3TN4"
},
"categories": [
"Northwest Territories"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"Ontario"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"National"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": "https://philanthropy.cdn.redcross.ca/timeline/July2020-3.jpg"
},
"categories": [
"British Columbia"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"Alberta"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"Prince Edward Island"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"National"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"National"
]
}
]
};
var categoriesToEventsMap = timelineData.events.reduce((res, event) => {
event.categories.forEach(c=> {
res = {
...res,
[c.toLowerCase()]: [...(res[c.toLowerCase()] || []), event]
}
});
return res;
}, {})
var result = filters.filters.reduce((acc, filter) => {
let events = []
const filterName = filter.name.replace(' ', '_').toLowerCase();
filter.keywords.forEach((key)=>{
events = [...events, ...(categoriesToEventsMap[key.toLowerCase()] || [])];
});
acc[filterName] = [...(acc[filterName] || []), ...events]
return acc;
}, {});
console.log(result);
So I have a bunch of JSON data and it contains a few fields. for example:
[{
"id": "XXX",
"version": 1,
"head": {
"text": "Main title",
"sub": {
"value": "next"
},
"place": "secondary"
},
"body": [{
"id": "XXX1",
"info": "three little birds",
"extended": {
"spl": {
"text": "song",
"type": {
"value": "a"
}
}
}
},
{
"id": "XXX2",
"info": [
"how are you?"
],
"extended": {
"spl": {
"text": "just",
"non-type": {
"value": "abc"
}
}
}
}
]
}]
what I'm trying to do is kind of conversion table (from a different JSON file)
if a field has the value 'a' replace it with 'some other text..' etc.
I have a service for the JSON pipeline, so I guess this is the right place to do the replacement.
so for this example, I have the JSON above and in my conversion table I have the following terms:
next: forward,
song: music,
a: option1,
just: from
etc...
What you are looking for can be achieved with templates. Replace the variable sections with some specific markers that you can find and replace from some external tools such as perl or sed.
For example, you could have a template.json with something like this:
...
"type": {
"value": "##VALUE##"
}
...
Then when you need the actual JSON, you could pass this though an intermediate script that replaces these templates with actual data.
cat template.json | sed -e 's/##VALUE##/my_value/' > target.json
Alternatively, with Perl:
cat template.json | perl -pi -e 's:\#\#VALUE\#\#:my_value:' > target.json
The best way is to parse it, replace the text in the object, and then stringify it.
The next best way is to use a regular expression.
In this example, I catch exceptions if path cannot be indexed, and use ['type'] instead of .type so it will scale to indexing 'non-type' if you wish.
const data = `[{
"id": "XXX",
"version": 1,
"head": {
"text": "Main title",
"sub": {
"value": "next"
},
"place": "secondary"
},
"body": [{
"id": "XXX1",
"info": "three little birds",
"extended": {
"spl": {
"text": "song",
"type": {
"value": "a"
}
}
}
},
{
"id": "XXX2",
"info": [
"how are you?"
],
"extended": {
"spl": {
"text": "just",
"non-type": {
"value": "abc"
}
}
}
}
]
}]
`
const o = JSON.parse(data)
o[0].body.forEach(b => {
try {
if (b.extended.spl['type'].value === 'a') {
b.extended.spl['type'].value = 'CHANGED'
}
} catch (e) {}
})
const newData = JSON.stringify(o, null, 2)
console.log(newData)
A string replace approach will work if you know and can rely on your source conforming, such as the only "value" is inside "type"
const data = `[{
"id": "XXX",
"version": 1,
"head": {
"text": "Main title",
"sub": {
"value": "next"
},
"place": "secondary"
},
"body": [{
"id": "XXX1",
"info": "three little birds",
"extended": {
"spl": {
"text": "song",
"type": {
"value": "a"
}
}
}
},
{
"id": "XXX2",
"info": [
"how are you?"
],
"extended": {
"spl": {
"text": "just",
"non-type": {
"value": "abc"
}
}
}
}
]
}]
`
const newData = data.replace(/"value": "a"/g, '"value": "NEWVALUE"')
console.log(newData)
I need to take the data from below mentioned array of object which has maximum length of nested array object. As per below my request, id : 2 values has 3 objects, result will be as mentioned below.
Anyone help me using lodash or some javascript function to achieve this.
Sample Request:
[{
"id": 1,
"values": [
{
"sub": "fr",
"name": "foobar1"
},
{
"sub": "en",
"name": "foobar2"
}
]
},
{
"id": 2,
"values": [
{
"sub": "fr",
"name": "foobar3"
},
{
"sub": "en",
"name": "foobar4"
},
{
"sub": "ts",
"name": "foobar5"
},
]
}]
Expected output:
"values": [
{
"sub": "fr",
"name": "foobar3"
},
{
"sub": "en",
"name": "foobar4"
},
{
"sub": "ts",
"name": "foobar5"
},
]
}]
This can be achieved using the native javascript reduce function as follows
var source = [...];
source.reduce((max, cur) => cur.values.length > max.values.length ? cur : max, source[0])
I have an id and i to filter a multidimensional array with these. My code is:
service.fakedata.map(f=>{
f.results.map(r=>{
r = r.filter(m=> m.rId !== id)
})
})
and my array is :
"services": [
{
"id": "1839f72e-fa73-47de-b119-49fb971a5730",
"name": "In I/O Route",
"url": "http://wwww.in.io/[param1]/[param2]",
"inputParams": [
{
"id": "e74a6229-4c08-43a1-961f-abeb887fa90e",
"name": "in1",
"datatype": "string"
},
{
"id": "e74a6229-4c08-43a1-961f-abeb887fa90o",
"name": "in2",
"datatype": "string"
}
],
"isArrayResult": false,
"results": [
{
"id": "ef7c98db-9f12-45a8-b3fb-7d09a82abe3d",
"name": "out1",
"datatype": "string",
"fakedatatype": [
"address",
"city"
]
},
{
"id": "9b178ded-af27-43df-920f-daab5ad439b9",
"name": "out2",
"datatype": "string",
"fakedatatype": [
"internet",
"url"
]
}
],
"routeParameters": [
"param1",
"param2"
],
"fakedata": [
{
"id": "b0376694-9612-43d2-93ed-c74264df962e",
"url": "http://wwww.in.io/wood/good",
"params": [
{
"key": "param1",
"value": "wood"
},
{
"key": "param2",
"value": "good"
}
],
"inputParams": [
{
"iId":"e74a6229-4c08-43a1-961f-abeb887fa90e",
"key": "in1",
"value": "m"
},
{
"iId":"e74a6229-4c08-43a1-961f-abeb887fa90o",
"key": "in2",
"value": "z"
}
],
"results": [
{
"rId": "ef7c98db-9f12-45a8-b3fb-7d09a82abe3d",
"key": "out1",
"value": "result1",
"fakedatatype": [
"address",
"city"
]
},
{
"rId": "9b178ded-af27-43df-920f-daab5ad439b9",
"key": "out2",
"value": "result2",
"fakedatatype": [
"internet",
"url"
]
}
]
}
]
}
]
In this case filter is working (when I check with console.log) but it doesn't change fakedata array.
What was wrong with my code?
From https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/map
The map() method creates a new array with the results of calling a provided function on every element in the calling array.
base on #H77 suggestion i change my code and now my code is look like this and everything work well
const s = service.fakedata.map(f=>{
f.results = f.results.map(r=>{
return r.filter(m=> m.rId !== id)
})
})