I have json collection, which is contains nested elements as an array or key value pair and can be nested upto any length. I need to pass through an array, and find the items within it and convert them with their respective values.
For example, in the given below array, I have an Array
One function to just get the values
1. I will pass this array to find out these two cells within the JSON collection and convert them into value. These values can be anywhere in the tree. I need to pick up the cell and their parent node. and it should search them put their respective value in it so it will chanege from ["TRC030-A", "TRSEE050-A"] to [22, 12]
One function to just sum up the values
2. Please note there are collections, and in them, the cell is same. but if I pass the "NSEE050-A","NSEE060-A" in the example, it should pick them and put the value and sum them up
I need to do this javascript recursively.
Kind regards,
{
"MusicVersion": "1.0.0",
"validationVersion": "1.0.0",
"submissionStage": "editing / submitted for approval etc.",
"PiaonoData": {
"musicacademies": [
{
"name": "Music Name",
}]
},
"MainData": {
},
}
You could use a Map to map the keys in your search-array to their index in that same array. That map will allow to check quickly whether a property in the data matches any property and give its index. It would also work with indexOf, but a Map is faster.
For the rest is a recursive function: it can be exited as soon as all keys have been found:
function mapKeys(obj, keys) {
const map = new Map(keys.map((key, i) => [key, i]));
const result = [];
function recur(obj) {
for (prop in obj) {
if (Object(obj[prop]) === obj[prop]) {
recur(obj[prop]);
} else if (map.has(prop)) {
result[map.get(prop)] = obj[prop];
map.delete(prop);
if (!map.size) return;
}
}
}
recur(obj);
return result;
}
// Sample data
const data = {"MusicVersion": "1.0.0","validationVersion": "1.0.0","submissionStage": "editing / submitted for approval etc.","PiaonoData": {"musicacademies": [{"name": "Music Name","id": "Music ID / UPIN","data": "See Example Form Object","SCI040": "newly admitted member"}]},"MainData": {"mainBalance": {"CAATOT" : 0,"AFC020-A": 11,"TRC030-A": 22,"TRC040-A": 33,},"nonMainData": {"TRSEE050-A": 12,"staffEmoluments" : [{"NSEE050-A": 12,"NSEE050-B": 22,"NSEE050-C": 40,"NSEE050-D": 54},{"NGEE050-A": 36,"NGEE050-B": 41,"NGEE050-C": 9,"NGEE050-D": 0},{"NLEE050-A": 1,"NLEE050-B": 3,"NLEE050-C": 7,"NLEE050-D": 9}],"MuiscSpecialPayments": [{"LSRP010-A": 12,"LSRP010-B": 22,"LSRP010-C": 40,"LSRP010-D": 54},{"LDSP010-A": 36,"LDSP010-B": 41,"LDSP010-C": 9,"LDSP010-D": 0},{"LDSP010-A": 1,"LDSP010-B": 3,"LDSP010-C": 7,"LSSP010-D": 9}],"MusicConversions": [{"type": "simple/complex/conversion","TATI010-A": 1,"TATI010-B": 3,"TATI020-A": 7,"TATI030-B": 9}]}},"MusicData": {"AatOverview": { "TATI010-A": 1,"ABCD": 3,"DEF": 7,"KLM": 9},"acOverview": {"TATI010-A": 1,"ATAATI010-B": 3,"OPQ": 7,"ATAATI030-B": 9,},"musicacademies": [{"name": "Music Name","id": "MusicID","data": "See Example Form Object","MCI040": "Newly admitted"}]},"otherMusicData": { "tbc": null },"MusicCompletionStatuses": { "tbc": null },"MusicValidationExplanations": {"ABC1001": {"fieldValue": "600","userComment": "Extra spend"},"ABS1196": {"fieldValue": "30","userComment": "This is the reason "}},"lastUpdatedBy": "user namer","lastUpdatedDate": "2016-04-23T18:25:43.511Z"};
console.log(mapKeys(data, ["TRC030-A", "NSEE050-A"]));
Related
I have a class that contains a field called 'notes'. Its data type is array. In the mutation, I'm able to save data on the field. problem is it overwrites the value. I want to add value in the array. how do I do it? here's my mutation. I know I'm not doing the right thing, but can't find it in the documentation as well
mutation {
updateParcel(input: { id: "B6aESEwWcA", fields: { notes: ["wow"]}}) {
parcel {
objectId
notes {
... on Element {
value
}
}
}
}
}
I have a group for which elements after reduction look like this pseudocode :
{
key:"somevalue",
value: {
sum: the_total,
names:{
a: a_number,
b: b_number,
c:c_number
}
}
}
In my dc-js geoChoropleth graph the valueAccessor is (d) => d.value.sum
In my title, I would like to use the names component of my reduction. But when I use .title((d) => {...}), I can onjly access the key and the value resulting from the valueAccessor function instead of the original record.
Is that meant to be ?
This is a peculiarity of the geoChoropleth chart.
Most charts bind the group data directly to chart elements, but since the geoChoropleth chart has two sources of data, the map and the group, it binds the map data and hides the group data.
Here is the direct culprit:
_renderTitles (regionG, layerIndex, data) {
if (this.renderTitle()) {
regionG.selectAll('title').text(d => {
const key = this._getKey(layerIndex, d);
const value = data[key];
return this.title()({key: key, value: value});
});
}
}
It is creating key/value objects itself, and the value, as you deduced, comes from the valueAccessor:
_generateLayeredData () {
const data = {};
const groupAll = this.data();
for (let i = 0; i < groupAll.length; ++i) {
data[this.keyAccessor()(groupAll[i])] = this.valueAccessor()(groupAll[i]);
}
return data;
}
Sorry this is not a complete answer, but I would suggest adding a pretransition handler that replaces the titles, or alternately, using the key passed to the title accessor to lookup the data you need.
As I noted in the issue linked above, I think this is a pretty serious design bug.
I am attempting to write either an array function or a dynamic array to Excel via a UDF written in Excel DNA (v.0.34). My result is always a single value instead of the array. What am I doing wrong?
[ExcelFunction(Name = "WriteTestArray")]
public static object[,] WriteTestArray()
{
try
{
return new object[2, 2] { { "one", "two" }, { "three", "four" } };
}
catch
{
return new object[,] { { ExcelError.ExcelErrorValue } };
}
}
For array functions to work with Excel (before the 'dynamic array' support that comes one day in a future version) you need to select the target range, then type in your formula and press Ctrl+Shift+Enter to commit it as an array formula. It will be indicated by curly brackets when displayed - e.g. {=MyFunc(...)}
I am using firebase 3.0, I see examples for the firebase 2.x versions, however they seem to not work in 3.0. I have a simple structure that I want to have returned to me sorted by value.
{
"Regions" : {
"All" : 0,
"Eastern & Southern Africa" : 1,
"Global" : 6,
"Himalayas" : 2,
"Mekong" : 3,
"Mesoamerica" : 5,
"West Africa" : 4
}
}
The code I am using returns the json, however it is not sorted by value, it is sorted alphabetically.
var config = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "servir-activity-database.firebaseapp.com",
databaseURL: "https://servir-activity-database.firebaseio.com",
storageBucket: "",
};
firebase.initializeApp(config);
var theRegions;
firebase.database().ref('Regions/').orderByChild('value').on('value', function (regions) {
theRegions = regions.val();
loadRegions(theRegions);
});
function loadRegions(which)
{
$.each(which, function (i, value) {
$('#ddlRegions').append($('<option>').text(i).attr('value', value));
});
}
I realize that I can do the sort on the client side, however this seems like a simple thing that can be returned sorted and I am probably missing something really simple.
This is a really long winded answer and is way more than is needed to answer the question, but should probably be considered:
One of the life lessons Firebase teaches us is that disassociating key names from the data is usually a good idea. I have (several times) coded myself into a corner because I used what I thought was a static key name, only to find it needed to be changed later. So let me expound on that briefly:
For example, say you have a users node
Frank_Jones: Madagascar
Leroy_Jenkins: UBRS
and suppose Frank decides that he no longer wants to be using the name 'Frank', but instead wants to be called 'Puf'
In that case every single node in your entire database would then have to be updated to refer back to the newly called Puf_Jones node. Ugh.
To avoid this issue, let Firebase generate your node names with childByAutoId, and let your values be children. This is a 'randomly' created node name that is guaranteed to be discreet.
A better Firebase Structure for your data would be
Regions
-Ykjoas99joksjk
region_name: "Himalayas"
rank: 2
-Jlioksjnfjp987
region_name: "Eastern & Southern Africa"
rank: 1
-J989j99ajskmds
region_name: "West Africa"
rank: 4
The -Ykjoas99joksjk etc node names are created by Firebase.
As you can see we now have a name and rank for each region. Let's say you wanted to add average summer temperature:
-Ykjoas99joksjk
region_name: "Himalayas"
rank: 2
temp: 77F
This allows your Firebase structure to be elastic depending on your needs.
(some Swift code to follow but you'll get the idea)
To get the region names in order
let ref = myRootRef.childByAppendingPath("Regions")
ref.queryOrderedByChild("region_name").observeEventType(
.ChildAdded, withBlock : { snapshot in
print(snapshot)
})
To get the two highest ranks
ref.queryOrderedByChild("rank").queryLimitedToLast(2).observeEventType(
.ChildAdded, withBlock : { snapshot in
print(snapshot)
})
and the Swift answer to your question with your existing Firebase Structure:
regionsRef.queryOrderedByValue().observeEventType(.ChildAdded, withBlock: {
snapshot in
print(snapshot)
})
Here's my lol translation that needs to be fixed...
firebase.database().ref('Regions').orderByValue.on('value', function (snapshot) {
loadRegions(snapshot.val());
});
Thank you #Jay, your answer was just long winded enough! I had to change the code part from swift to javascript but i followed the autoid for the key method as you described. Here is the js i used to process the return data.
firebase.database().ref('Regions').orderByChild("rank").on('child_added', function (regions) {
loadRegions(regions.exportVal());
});
firebase.database().ref('Regions').orderByChild("rank").on('child_removed', function (regions) {
removeRegion(regions.exportVal());
});
function removeRegion(which)
{
$("#ddlRegions option[value="+which.rank+"]").remove();
}
function loadRegions(which)
{
var count = 0;
var RegionValue;
$.each(which, function (i, value) {
if (count % 2 == 0) {
RegionValue = value;
}
else {
$('#ddlRegions').append($('<option>').text(value).attr('value', RegionValue));
}
count++;
});
}
I have below a structured Mongo Document:
{
"_id": value,
"imageShared": {
"imageid": value,
"commentdatadoc": [
{
"whocommented": value,
"commenttext": value,
"commenttimestamp": isodate(111)
},
{
"whocommented": value,
"commenttext": value,
"commenttimestamp": isodate(444)
},
{
"whocommented": value,
"commenttext": value,
"commenttimestamp": isodate(222)
}
]
}
};
Here I want to sort the field commenttimestamp desc. I tried the way below but it is not working...
Query getComments = new Query();
getComments.addCriteria(Criteria.where("imageShared.imageId").is(imageId)).
with(new Sort(Sort.Direction.DESC,"imageShared.commentDataDoc"));
SharedMediaCollec sharedMediaCollec = mongoTemplate.findOne(getComments, SharedMediaCollec.class);
Does anyone have an idea how to sort a document field which is inside array?
When you need to get all documents anyway, it might be far easier to do the sorting in C# after you received the data from MongoDB. An elegant way to do this automatically would be to represent the commentdatadoc array in your C# object with a SortedSet.
But when you definitely want a database-sided solution, you can do it with an aggregation pipeline consisting of a $match-step, a $unwind step and a $sort step. To perform an aggregation with the C# driver, call collection.Aggregate and then set the aggregation stages at the returned IAggregateFluent interface.