I have a set of JSON - that i need to iterate over as I essentially need to create a string which contains certain identifiers in it. At the moment I am mapping over the data and then over stimulus list. ( I have the index which from the event as I only need data from that index).
The problem I have is the cell_id is always the same . And I need to create a string.
const key = `cell_Id${cell_id}:step_Id${item.step_id}:study_id${studyId}:stim_id${item.stimulus_id}`
I suspect I need to add things to an object as I am interating over the data - what is the best way to do this?
thanks
Here is the JSON
{
"study_id": 16,
"data": [
{
"cell_id": 23,
"stimulus_list": [
{
"stimulus_id": 96,
"step_id": 62
}
]
},
{
"cell_id": 24,
"stimulus_list": [
{
"stimulus_id": 95,
"step_id": 61
}
]
}
]
}
data
.map(item => item.stimulus_list)
.map(item => item[index]);
You can have a nested map over the data and then flatten the result using reduce.
const obj = {
"study_id": 16,
"data": [
{
"cell_id": 23,
"stimulus_list": [
{
"stimulus_id": 96,
"step_id": 62
}
]
},
{
"cell_id": 24,
"stimulus_list": [
{
"stimulus_id": 95,
"step_id": 61
}
]
}
]
}
const res = obj.data
.map(item => {
return [].concat(item.stimulus_list.map(stimulus => `cell_Id${item.cell_id}:step_Id${stimulus.step_id}:study_id${obj.study_id}:stim_id${stimulus.stimulus_id}`))
}).reduce((acc, item) => {
acc = acc.concat(item)
return acc;
}, [])
console.log(res)
Related
I have a nested array and want to push the first item from one of the arrays to state,
the Parent Array like this
"options": [
{
"id": 76,
"label_en": "Disk Storage",
"type": "text",
"product_id": 20,
"values": [
{
"id": 133,
"name_en": "32 GigByte",
"display_value": null,
"randam_key": "8596598ED", // this the target value I want to save
"option_id": 76
},
{
"id": 134,
"name_en": "16 GigByte",
"display_value": null,
"randam_key": "895454HG",
"option_id": 76
}
]
},
{
.....
}
]
every object from the "options - Parent" Array has a values array,
and every object of the values array has a randam_key
I want to save the first random key value from every object of the values array,
at the same time, i have a function that's store all values into a state to be like
//result
bodyQuery = {
"product_id": 20,
"values": {
"randam_key1": "895454HG",
"randam_key2": "FFJFOF568",
"randam_key3": "FDVHFDVD566"
}
}
const getUpdatedPrice = (randam_key: string, handleKey: string) => {
setBodyQuery((prevState) => ({
...prevState,
values: {
...prevState.values,
[handleKey]: randam_key,
},
}));
};
So what I tried is to get the keys 'Check the Live Code at the bottom', but i don't know how can I call getUpdatedPrice() to save the data as expected when the screen mounted.
the second case I have that saves the random keys after iterated the arrays and when I press to any item i call the getUpdatedPrice()
and this works very well but i need to do this behavior when screen mounted useEffect()!
#Second Case - Work as expected
{options.map((option) => {
....
{option.values.map((value: valueOptionProp, index) => {
// button
onPress={()=> getUpdatedPrice(
value.randam_key,
'randam_key' + (options.indexOf(option) + 1),
);
}
})}
})}
live code
{/* let optionsArr=[]
options.map((option) => {
optionsArr.push(option.values);
}
*/}
// the result of the above code is
optionsArr = [
[
{
display_value: null,
id: 133,
name_en: '32 GigByte',
option_id: 76,
randam_key: '8596598ED',
},
{
display_value: null,
id: 134,
name_en: '16 GigByte',
option_id: 76,
randam_key: '895454HG',
},
],
[
{
display_value: '#FFF',
id: 135,
name_en: 'ًWhite',
option_id: 77,
randam_key: 'FGFFDCF54',
},
{
display_value: '#85FD',
id: 136,
name_en: 'Golden',
option_id: 77,
randam_key: 'FFJFOF568',
},
],
[
{
display_value: 'Url Image Here',
id: 137,
name_en: 'image 1',
option_id: 78,
randam_key: 'HGHVDF84585',
},
{
display_value: 'Url Image Here',
id: 138,
name_en: 'Image 2',
option_id: 78,
randam_key: 'FDVHFDVD566',
},
],
];
let first_randomKey = optionsArr.map(val=>val[0].randam_key);
console.log(first_randomKey);
#Edit
I try it like this and it works well!
If there any other solutions please let me know!
useEffect(() => {
let optionsArr: any[] = [];
item.options.map((option) => {
optionsArr.push(option.values);
});
let first_randomKey = optionsArr.map((val) => val[0].randam_key);
let keys = first_randomKey.map((_itemKeys) => {
getUpdatedPrice(
_itemKeys,
'randam_key' + (first_randomKey.indexOf(_itemKeys) + 1),
);
});
Promise.all(keys).then(() => {
isUpdated.current = true;
});
}, [item.options]);
useEffect(() => {
if (isUpdated.current) {
console.log('bodyQuery', bodyQuery);
}
}, [bodyQuery]);
There are a number of inconsistencies and inefficiencies in your final code, mostly around your use of Array.prototype.map().
Array.prototype.map() returns a new array, so declaring optionsArr and then using map() to push to it is redundant. You use it correctly in the next line however, when you assign first_randomKey by calling map() on the aforementioned optionsArr.
In your final map() call you are manually finding the index of the current iterated _itemsKeys but this is unnecessary as map() provides this for you as the second parameter of the callback. Again, elsewhere in your question you pass the index, but even then you aren't using it but manually finding the index.
The main inefficiency is that you using three map() calls for what could be achieved with one, here using destructuring assignment to access desired property, and leveraging the implicitly passed index parameter provided by map().
const keys = item.options.map(({ values: [{ randam_key }] }, index) =>
getUpdatedPrice(randam_key, 'randam_key' + (index + 1)));
or without destructuring
const keys = item.options.map((option, index) => {
const randam_key = option.values[0].randam_key;
return getUpdatedPrice(randam_key, 'randam_key' + (index + 1));
});
const item = { "options": [{ id: 1, values: [{ id: 133, randam_key: "8596598ED" }, { id: 134, randam_key: "895454HG", }] }, { id: 1, values: [{ id: 135, randam_key: 'FGFFDCF54', }, { id: 136, randam_key: 'FFJFOF568', },] }, { id: 1, values: [{ id: 137, randam_key: 'HGHVDF84585', }, { id: 138, randam_key: 'FDVHFDVD566', },] }] }
const getUpdatedPrice = async (key, indexedKey) => {
return [key, indexedKey]
}
const keys = item.options.map(({ values: [{ randam_key }] }, index) =>
getUpdatedPrice(randam_key, 'randam_key' + (index + 1)));
Promise.all(keys).then((result) => {
console.log(result)
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
i have an array like this,
data = [
{
DOCDT: "2020-06-06T18:59:48.000Z",
DOCNO: "001",
IREF1: "50",
IREF2: "100",
NETAMOUNT: 30000,
},
{
DOCDT: "2020-06-06T18:59:48.000Z",
DOCNO: 2,
IREF1: 40,
IREF2: 90,
NETAMOUNT: 40000,
},
];
i want to compare its keys to another array which is this
jsonData = [
"DOCNO",
"DOCDT",
"IREF1",
"IREF2",
"NETAMOUNT"
]
i want to change the order of data array based on jsonData, is there any way in es6 or javascript to do that.
i tried using this but it doesnt work
this.data.sort(function(a, b){
return jsonData.indexOf(a) - jsonData.indexOf(b);
});
Write sortObject method and use it over map. I shuffled data keys order to make the output is expected. Hope this helps.
data = [
{
IREF1: "50",
IREF2: "100",
NETAMOUNT: 30000,
DOCDT: "2020-06-06T18:59:48.000Z",
DOCNO: "001",
},
{
DOCNO: 2,
IREF1: 40,
DOCDT: "2020-06-06T18:59:48.000Z",
IREF2: 90,
NETAMOUNT: 40000,
},
];
jsonData = ["DOCNO", "DOCDT", "IREF1", "IREF2", "NETAMOUNT"];
// When Object.fromEntries not available in your environment
const objFromEntries = (arr) =>
arr.reduce((acc, [key, val]) => ((acc[key] = val), acc), {});
const sortObject = (obj) =>
objFromEntries(
Object.entries(obj).sort(
([a], [b]) => jsonData.indexOf(a) - jsonData.indexOf(b)
)
);
const updated = data.map(sortObject);
console.log(updated);
I have a collection of players like this:
{
"_id": ObjectId("5eb93f8efd259cd7fbf49d55"),
"id_test": 132
"name": "John Doe"
},
{
"_id": ObjectId("5eb93f8efd259cd7fbf49d33"),
"id_test": 90
"name": "Tom White"
},
{
"_id": ObjectId("5eb93f8efd259cd7fbf49d31"),
"id_test": 999
"name": "Mike Barry"
}
I have an array of Ids with id_test:
const arrayIds = [ 132, 43, 90, 555];
Then I want to get elements not matched in array (not in collection with $nin). Im my example I need to output: [43, 555]
Something like this: (but I want to know if it's possible with one single query):
const players = await db.collection('players').find(
{ id_test: { "$in": arrayIds } } )
.toArray();
const playersIds = players.map(e => e.id_test); // [132, 90]
const final = arrayIds.filter(i => !playersIds.includes(i)) // [43, 555]
Yes, you can do that in a single query by aggregation,
First, we search the players, then create an array of their id_test, then by $setDifference get the difference you want
const players = await db.collection('players').aggregate(
[ { $match :
{
id_test : { "$in": arrayIds }
}
},
{
$group:
{
_id: null,
id_test: { $push: "$id_test" }
}
},
{ $project: { final:{ $setDifference: [ arrayIds , "$id_test" ] }, _id: 0 } }
]
);
const final = players.final // [43, 555]
Just to clarify this is what I mean by "inverted map":
const foo =
{ "a": 10
, "b": 20
};
const foo_inverted =
{ "10": "a"
, "20": "b"
};
I have this object representing a file:
const file =
{ id: 100
, tags: [20, 30]
};
Given a list of files I need to build a map that allows me to find all files with a given tag.
From this:
const files =
[ { id: 100
, tags: [20, 30]
}
, { id: 200
, tags: [20, 40]
}
];
To that:
{ "20": { "100": 1, "200": 1 }
, "30": { "100": 1 }
, "40": { "200": 1 }
}
I ended up with this code which does the job:
const tag_file = (tag_id, file_id) => ({[tag_id]: {[file_id]: 1}});
const mergeDeepAll = reduce(mergeDeepRight, {});
const tag_map = compose(mergeDeepAll, lift(tag_file));
const tags_map = compose(mergeDeepAll, map(({id, tags}) => tag_map(tags, [id])));
tags_map(files);
//=> { "20": { "100": 1, "200": 1 }
//=> , "30": { "100": 1 }
//=> , "40": { "200": 1 }
//=> }
Question: am I missing any functional programming concepts that would have allowed me to express this better?
Create an a function that generates pairs [tag, id] for each object, using a Array.map() (idByTags). Using R.chain convert all objects to such pairs and flatten them. Group by the tag (R.head), and then map the object (R.mapObjIndexed) and count by the id (R.last):
const { pipe, chain, groupBy, head, mapObjIndexed, countBy, last } = R
const idByTags = ({ id, tags }) => tags.map(tag => [tag, id])
const fn = pipe(
chain(idByTags),
groupBy(head),
mapObjIndexed(countBy(last))
)
const files = [{"id":100,"tags":[20,30]},{"id":200,"tags":[20,40]}]
const result = fn(files)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
not sure why you would need ramda, can do it with reduce and forEach
const files = [{
id: 100,
tags: [20, 30]
}, {
id: 200,
tags: [20, 40]
}];
// loop over the array to make an object
const result = files.reduce((obj, file) => {
// loop over the tags
file.tags.forEach(
tag =>
obj[tag] ? // have we seen the tag?
obj[tag].push(file.id) : // yes
obj[tag] = [file.id] // no
)
return obj // return the object for reduce
}, {})
console.log(result)
AFTER YOUR EDIT
const files = [{
id: 100,
tags: [20, 30]
}, {
id: 200,
tags: [20, 40]
}];
// loop over the array to make an object
const result = files.reduce((obj, file) => {
// loop over the tags
file.tags.forEach(
tag => {
obj[tag] = obj[tag] || {} // have we seen the tag?
obj[tag][file.id] = 1 //
})
return obj // return the object for reduce
}, {})
console.log(result)
I am receiving the following structure from a system. I am attempting to bend it into the form needed for a particular graph utilizing chartjs. Given the JSON data structure … an array of objects in an object:
{
"chart": [
{
"date": "2018-10-29",
"done": 3,
"todo": 10
},
{
"date": "2018-10-30",
"done": 4,
"todo": 7
},
{
"date": "2018-10-31",
"done": 5,
"todo": 12
}
]
}
I need the desired JSON data structure ... an object of arrays (in one array, in one object)
{
"chart": [{
"date": [
"2018-10-29",
"2018-10-29",
"2018-10-31"
],
"done": [
3,
4,
5
],
"todo": [
10,
7,
12
]
}]
}
I have attempted to use the .map function but I don't seem to have the correct map-fu.
You could take an object and get all keys with ther values in single array.
var data = { chart: [{ date: "2018-10-29", done: 3, todo: 10 }, { date: "2018-10-30", done: 4, todo: 7 }, { date: "2018-10-31", done: 5, todo: 12 }] },
result = { chart: data.chart.reduce((r, o) => {
Object.entries(o).forEach(([k, v]) => (r[k] = r[k] || []).push(v));
return r;
}, {})
};
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
What about using reduce ?
const output = input.reduce((acc, curr) => ({
date: acc.date.concat(curr.date),
done: acc.done.concat(curr.done),
todo: acc.todo.concat(curr.todo),
}), { date: [], done: [], todo: [] });
const chartData = {
chart: [output],
};
Reference for reduce is here : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/reduce
Here's a very explicit solution. There may be some slicker Javascript solutions; certainly you can do multiple .map calls, but that makes it less efficient.
// Variables
var dates = [];
var doneValues = [];
var todoValues = [];
// Loop through the original data once, collect the data.
originalJSON.forEach(function(data) {
dates.push(data["date"]);
doneValues .push(data["done"]);
todoValues .push(data["todo"]);
});
// Put it all together.
return {"chart": [{"date": dates, "done": doneValues , "todo": todoValues}]};
Modify it to suit your needs.