I have reference array which has values ["a","b","c","d"] .and i have another array which is obtaining as part of API which is not very consistent format .i am pointing some examples below
case 1.`{
names : ["a"],
value : [ [0],[0],[2],[4],... ]
}`
case 2. `{
names : ["a","c"],
value : [ [0,2],[0,0],[2,3],[4,4],... ]
}`
the result could be in any combination
but my requirement is to assign the value of incoming result into another array
having index same as my reference array
for example : in
case 1
`
let finalArray = [["0",null,null,null],
["0",null,null,null],
["2",null,null,null].... ]
`
for case 2:
`let finalArray = [["0",null,"2",null],
["0",null,"0",null],
["2",null,"3",null].... ]
`
alse attaching a fiddle with my inputs below
jsfiddle link to problem
any suggestions?
i am trying to use minimal for loops for performance optimization
Hope this will be helpful.
var refArray = ["a","b","c","d"];
setTimeout(()=>{processResult({
"names" : ["a"],
"value" : [ [0],[0],[2],[4]]
})},2000);
setTimeout(()=>{processResult(
{
"names" : ["a","c"],
"value" : [ [0,2],[0,0],[2,3],[4,4]]
})},4000);
setTimeout(()=>{processResult(
{
"names" : ["d","c"],
"value" : [ [0,2],[0,0],[2,3],[4,4]]
})},6000);
function processResult (result) {
let res = result.value;
let resArray = res.map((el)=>{
let k=Array(refArray.length).fill(null);
refArray.forEach((e,i)=>{
let indx = result.names.indexOf(e);
if(indx>=0){
k[i] = el[indx]
}
});
return k;
})
console.log("result",resArray)
}
Below is what I could think of that would require least iterations.
var refArray = ["a", "b", "c", "d"];
setTimeout(()=>{processResult({
"names" : ["a"],
"value" : [ [0],[0],[2],[4]]
})},2000);
setTimeout(()=>{processResult(
{
"names" : ["a","c"],
"value" : [ [0,2],[0,0],[2,3],[4,4]]
})},4000);
setTimeout(()=>{processResult(
{
"names" : ["d","c"],
"value" : [ [0,2],[0,0],[2,3],[4,4]]
})},6000);
function processResult(result) {
//This map will contain max names matched in the result
var maxItemsFromResult = {};
//Find the indexes in refArray and fill map
//e.g. 1st- {0:0}, 2nd - {0:0, 1:2}, 3rd - {0:3, 1:2}
result.names.forEach((item, index) => {
let indexFound = refArray.indexOf(item);
if (indexFound > -1) {
maxItemsFromResult[index] = indexFound;
}
});
//for performance if no key matched exit
if (Object.keys(maxItemsFromResult).length < 1) {
return;
}
//This will be final result
let finalArray = [];
//Because finalArray's length shuld be total items in value array loop through it
result.value.forEach((item, itemIndex) => {
//Create a row
let valueArray = new Array(refArray.length).fill(null);
//Below will only loop matched keys and fill respective position/column in row
//i'm taking all the matched keys from current value[] before moving to next
Object.keys(maxItemsFromResult).forEach((key, index) => {
valueArray[maxItemsFromResult[key]] = item[index];//get item from matched key
});
finalArray.push(valueArray);
});
console.log(finalArray);
return finalArray;
}
Related
I've been trying to loop through a mulitnested json object but everytime it displays undefined. I've wanted to display playcount and the name of the song. I plan on using this with a bar chart.
I tried this expecting ['playcount', 'name']
function getData(){
$("#output").html("<b>hi there</b>");
$.getJSON('https://ws.audioscrobbler.com/2.0/?method=artist.gettopalbums&artist=drake&api_key=22102f7d3a814de0736edf670bd2c771&format=json',function(result){
console.log(result);
let testarray = result[0]['album'];
let newdata = [];
for (let i = 0; i < result.length; i++) {
testarray= result[i]['album']
console.log(testarray)
let item = []
item[0] = testarray[i]['playcount']
item[1] = testarray[i]['name']
newdata[j] = item
console.log(newdata);
}
console.log(newdata)
})
}
Let's first take a look at the data you are working with:
result = {
"topalbums":
{
"album":
[
{
"name": "So Far Gone",
"playcount": 12543719,
"mbid": "f05567cc-6ed3-40e0-bad1-7812478eecbe",
"url": "https://www.last.fm/music/Drake/So+Far+Gone",
"artist": { ... }
"image": [ ... ]
},
...
],
"#attr": { ... }
}
}
You are gettin an object that has a property with a key called topalbums. Top albums has two properties; an array called album and an object called #attr.
From the looks of it, you want to access the objects inside of the album array, and more specifically name and playcount.
Given the data you are working with I assume this is what you would be looking for:
let newdata =
[
{
"playcount": 123123
"name": "album name1"
},
{
"playcount": 12456543
"name": "album name2"
},
...
]
To achieve this you can alter your code in the following fashion:
function getData(){
$("#output").html("<b>hi there</b>");
$.getJSON('https://ws.audioscrobbler.com/2.0/?method=artist.gettopalbums&artist=drake&api_key=22102f7d3a814de0736edf670bd2c771&format=json',function(result){
console.log(result);
let albumArray = result["topalbums"]["album"]; // This gets you the album array
let newdata = [];
for (let i = 0; i < albumArray.length; i++) {
const albumSummary = {} // Create a new object
albumSummary["name"] = albumArray.name // Add name to the object
albumSummary["playcount"] = albumArray.playcount // Add playcount to the object
newdata.push(albumSummary) // Add the object to the array
}
console.log(newdata)
})
}
Alternatively, if you don't want an array of objects but an array of arrays like this [['playcount', 'name']...], you can alter the code above like this:
function getData(){
$("#output").html("<b>hi there</b>");
$.getJSON('https://ws.audioscrobbler.com/2.0/?method=artist.gettopalbums&artist=drake&api_key=22102f7d3a814de0736edf670bd2c771&format=json',function(result){
console.log(result);
let albumArray = result["topalbums"]["album"]; // This gets you the album array
let newdata = [];
for (let i = 0; i < albumArray.length; i++) {
const albumSummary = [] // Create a new array
albumSummary.push(albumArray.name) // Add name to the array
albumSummary.push(albumArray.playcount) // Add playcount to the array
newdata.push(albumSummary) // Add the array to the array
}
console.log(newdata)
})
}
Hope this helps!
Desired output--
[
{
"group1": {
"Token1": "123443423",
"Token2": "121414141"
},
"group2": {
"Token1": "123443423",
"Token2": "121414141"
}
}
]
Group1 and group2 is dynamic and also the token1 and token2 value is dynamic. So i write this way --
[ {`${group1}`:{
"Token1" : `${token1}`,
"Token2" : `${token2}`
},
`${group2}`:{
"Token1" : `${token1}`,
"Token2" : `${token2}`
}
}]
But ${group1} shows error unexpected token ` (template literate).
1. [Specific]
// helper function
function createGroup(groupName, token1, token2) {
const group = {};
group[groupName] = {
Token1: token1,
Token2: token2
};
return group;
}
//and then create a result output
var result = [
createGroup('group1', group1token1, group1token2),
createGroup('group2', group2token1, group2token2),
]
2. [More general] For multiple paramenters (more than fixed 2):
your parametersObject have to be as:
{
Token1: 'token_1_value_here',
Token2: 'token_2_value_here',
...
ParameterN: 'parameter_n_value_here',
...
}
And then:
// helper function 2
function createGroup(groupName, parametersObject) {
const group = {};
group[groupName] = parametersObject;
return group;
}
//and then create a result output
var result = [
createGroup('group1', group1parametersDto),
createGroup('group2', group2parametersDto)
]
in your way you can create object with variables value this way . there was syntax error in your approach, template literals are not allowed for object key inside object directly
var group = "group",
Token1 = "123443423",
Token2 = "121414141"
var newObject =
{
[group + "1"] : {Token1 , Token2},
[group + "2"] : {Token1 , Token2},
[group + "3"] : {Token1 , Token2},
[group + "4"] : {Token1 , Token2}
}
console.log(newObject)
there is also more easy way to do same which is more conveneint
example below
var object = {},
Token1 = "123443423",
Token2 = "121414141"
object["group1"] = {Token1,Token2}
object["group2"] = {Token1,Token2}
object["group3"] = {Token1,Token2}
console.log(object)
I want to find strings that has data from the strings from the array 2 in the array1 and save result as separate uniq array.
As can you see I search for not exact values. From the array1 values I know only part of the information, and I want to find the complete strings, with that information, in array1. And at the end I want to save what I found. So, I don't have a problem with finding here, but a problem with saving in the valid single JSON.
Array examples:
Array #1:
{
"overflow": [
"id:address:name:location:email",
...
"id2:address2:name2:location2:email2"
]
}
Array #2:
[
"location:email",
...
"location2:email2"
]
Code:
resultArr: function() {
var arr1 = '/var/log/1.json';
var arr2 = '/var/log/2.json';
var arrResult = '/var/log/result.json';
var arr2Obj = JSON.parse(fs.readFileSync(arr2, 'utf-8'));
for (var i = 0; i < arr2Obj.length; i++) {
var arr1Obj = JSON.parse(fs.readFileSync(arr1, 'utf-8'));
arr1Obj.overflow = arr1Obj.overflow.filter(function(e) {
return e.includes(arr2Obj[i])
});
fs.appendFile(arrResult, JSON.stringify(arr1Obj, null, 2), 'utf-8');
}
}
My result:
[{
"overflow": [
"id:address:name:location:email"
]
}{
"overflow": [
"id54:address54:name54:location54:email56"
]
}{
"overflow": [
"id2:address2:name2:location2:email2",
"id6:address6:name6:location2:email2"
]
}
What I really want:
{
"overflow": [
"id:address:name:location:email",
"id54:address54:name54:location54:email56",
"id6:address6:name6:location2:email2",
"id2:address2:name2:location2:email2"
]
}
Instead of reading the file again and again, and appending to the result repeatedly, just do both actions only once. All the rest should happen in memory.
You will also get better results (no risk for duplicates in result) when you swap the loops: put the filter action as the outer loop. For the inner loop you can use some, since one match is enough for the entry to be included:
resultArr: function() {
var arr1 = '/var/log/1.json',
arr2 = '/var/log/2.json',
arrResult = '/var/log/result.json',
arr2Obj = JSON.parse(fs.readFileSync(arr2, 'utf-8')),
arr1Obj = JSON.parse(fs.readFileSync(arr1, 'utf-8'));
arr1Obj.overflow = arr1Obj.overflow.filter(function(e) {
return arr2Obj.some(function (f) {
return e.includes(f)
});
});
fs.writeFileSync(arrResult, JSON.stringify(arr1Obj, null, 2), 'utf-8');
}
At each iteration, you're creating a new object and appening it to a file.
JSON is not a good format to append to.
You're replacing the array instead of adding fields to it.
You can do it that way, it should work :
resultArr: () => {
let arr1 = '/var/log/1.json';
let arr2 = '/var/log/2.json';
let arrResult = '/var/log/result.json';
let arr2Obj = JSON.parse(fs.readFileSync(arr2, 'utf-8'));
let arr1Obj = JSON.parse(fs.readFileSync(arr1, 'utf-8')); // reading only one time
arr1Obj.overflow = arr2Obj.map(value => {
return arr1Obj.overflow.filter(e => return e.includes(value))
});
fs.writeFileSync(arrResult, JSON.stringify(arr1Obj, null, 2), 'utf-8'); //Writing only one time
}
Array.map() executes the closure for each field in your array and group all the values returned by the closure in another array.
I also replaced some keywords to make your code more ES6 compliant. I you really want to append, you should use CSV and not JSON.
I have a JSON file like below:
[
{"fields":{category_class":"CAT2",category_name":"A"},"pk":1 },
{"fields":{category_class":"CAT1",category_name":"B"},"pk":2 },
{"fields":{category_class":"CAT1",category_name":"C"},"pk":3 },
{"fields":{category_class":"CAT2",category_name":"D"},"pk":4 },
{"fields":{category_class":"CAT3",category_name":"E"},"pk":5 },
{"fields":{category_class":"CAT1",category_name":"E"},"pk":6 },
]
I want to create an array of objects from the above JSON which will have two properties. i) CategoryClass ii) CategoryNameList. For example:
this.CategoryClass = "CAT1"
this.CategoryNameList = ['B','C','E']
Basically i want to select all categories name whose category class is CAT1 and so forth for other categories class. I tried this:
var category = function(categoryClass, categoryNameList){
this.categoryClass = categoryClass;
this.categoryList = categoryNameList;
}
var categories = [];
categories.push(new category('CAT1',['B','C','E'])
Need help.
You can use a simple filter on the array. You have a few double quotes that will cause an error in you code. But to filter only with CAT1 you can use the filter method
var cat1 = arr.filter( value => value.fields.category_class === "CAT1");
I would suggest this ES6 function, which creates an object keyed by category classes, providing the object with category names for each:
function groupByClass(data) {
return data.reduce( (acc, { fields } ) => {
(acc[fields.category_class] = acc[fields.category_class] || {
categoryClass: fields.category_class,
categoryNameList: []
}).categoryNameList.push(fields.category_name);
return acc;
}, {} );
}
// Sample data
var data = [
{"fields":{"category_class":"CAT2","category_name":"A"},"pk":1 },
{"fields":{"category_class":"CAT1","category_name":"B"},"pk":2 },
{"fields":{"category_class":"CAT1","category_name":"C"},"pk":3 },
{"fields":{"category_class":"CAT2","category_name":"D"},"pk":4 },
{"fields":{"category_class":"CAT3","category_name":"E"},"pk":5 },
{"fields":{"category_class":"CAT1","category_name":"E"},"pk":6 },
];
// Convert
var result = groupByClass(data);
// Outut
console.log(result);
// Example look-up:
console.log(result['CAT1']);
Question : Basically i want to select all categories name whose category class is CAT1 and so forth for other categories class
Solution :
function Select_CatName(catclass,array){
var CatNameList=[]
$(array).each(function(){
if(this.fields.category_class==catclass)
CatNameList.push(this.fields.category_name)
})
return CatNameList;
}
This function return the Desired Category Name List, you need to pass desired catclass and array of the data , as in this case it's your JSON.
Input :
Above function calling :
Output :
Hope It helps.
I have array from database with json_encode, like this :
"[{"uid":"595e7d","name":"Elephant"},{"uid":"701b03","name":"Bird"},{"uid":"29a8c","name":"Lion"}]"
but how to make the array just display the record not with the field/column name, when i show in javascript like this :
javascript array :
{
"595e7d": "Elephant",
"701b03": "Bird",
"29a8c": "Lion"
}
whether it should be done in php or javascript?
thankyou
Handle with javascript:
function transfrom (arrs){
return arrs.reduce((init, arr) => {
init[arr.uid] = arr.name
return init
}
, {})
}
//usage
let arrs = [{"uid":"595e7d","name":"Elephant"},{"uid":"701b03","name":"Bird"},{"uid":"29a8c","name":"Lion"}]
transfrom(arrs)
// {595e7d: "Elephant", 701b03: "Bird", 29a8c: "Lion"}
Or you can handle it with PHP:
<?php
$arr = array (
array('uid' =>"595e7d", "name"=>"Elephant"),
array("uid" =>"701b03", "name" =>"Bird"),
array("uid" =>"29a8c", "name" =>"Lion")
);
function transform($v1, $v2) {
$v1[$v2["uid"]] = $v2["name"];
return $v1;
}
echo json_encode(array_reduce($arr, "transform", array()));
// {
// "595e7d": "Elephant",
// "701b03": "Bird",
// "29a8c": "Lion"
// }
?>
If I understood it correctly, you are looking for something like
var arr = [{"uid":"595e7d","name":"Elephant"},{"uid":"701b03","name":"Bird"},{"uid":"29a8c","name":"Lion"}];
var out = {};
arr.forEach(function(obj){
var tempArr = Object.values(obj);
out[tempArr[0]] = tempArr[1];
});
console.log(out);
Please note that the code is not too generic and may require modification based on your actual requirement.