I have an object that I need to transform into an array. Here is the code I have already:
for (var key in categoryData[p]) { // categorydata is an object, the "p" is because this is taking place in a loop (array of objects)
if (categoryData[p].hasOwnProperty(key)) {
var objToArray = $.map(categoryData[p], function(value, key) {
return [value];
});
}
}
Right now, this is returning:
0 : value
1 : value
2 : value
I want it to return:
Key : Value
Key : Value
Key : Value
But I haven't found a way to do this with my data. Any direction would be greatly appreciated!
Edit: Adding more information:
I want to sort from the highest to lowest value. For clarification, I want the data to look like this:
(key) (object)
"ABC" : 8
"DEF" : 7
"GHI" : 5
I am putting it into an array to begin with because I can't sort the values when they're in an object (as far as I know).
My data is fairly complex, in a CSV file, but the idea of it is:
ABC, DEF, GHI
8 , 7 , 5
Associative arrays aren't a thing in javascript. You can either have arrays denoted by [] with 0 based numeric indices, or objects denoted by {} that can store key-value pairs. The latter construct can be used as replacement to associative arrays (ie add arbitrary keys and values to it), but they cannot be treated like arrays.
What you want in this case is what you already have - a key/value store, except it's called an object.
edit
If you just want to sort the data regardless of datatypes
You can split your object into multiple objects with a single key-value pair, then create an array from these objects and sort them any way you like using Array.sort(). Here's a quick example of splitting your provided data into objects:
var originalData = {
"ABC" : 8,
"DEF" : 7,
"GHI" : 5,
},
sortableArray = [];
for (key in originalData) {
sortableArray.push({
"key" : key,
"value" : originalData[key]
});
}
This creates a new object and appends it to our sortable [] array. To sort it according to its original value, you need to supply a comparator function that accesses the value property of the objects.
sortableArray.sort(function(a,b) {
return a.value - b.value;
});
This should return an array of objects ordered by the value property of each object in ascending order. Simply switch a and b around to get a descending order sort.
Hope this helps!
The best approach to sort your data is to map your object into an array to look like this:
[
{
"key": someKey
"value": someValue
},
{
"key": someOtherKey
"value": someOtherValue
},
//...
]
using this code:
var objToArray = $.map(categoryData[p], function(value, key) {
return {"key": key, "value": value};
});
And then sort it using this code:
objToArray.sort(function(a, b) {
// if the values are numbers (otherwise you have to change this to addapt to your dataType)
return b.value - a.value; // to sort from highest to lowest or a.value - b.value to sort from lowest to highest
});
And then you can use it like:
objToArray[0].key; // to get the key of the first item
objToArray[3].value; // to get the value of the 4-th item
// ...
You can loop through them as well (for(var i = 0; i < objToArray.length; i++)...).
In ES6, Object.entries(a).sort((a, b) => a[1] < b[1] )
This will give you something like this
[
["ABC", 8]
["DEF", 7]
["GHI", 5]
]
the .entries step gives you the list of pairs and the .sort step sorts them by their second value
Related
I have a react update form and i wish to differentiate the form data and the current data to figure out what has changed dynamically.
Problem summarized
find the minimum differences between 2 nested objects. And output an array of changed properties paths. E.g. if department_id in the departments list at index 0 changes while the rest stays the same - the algorithm should output ['departments'].
Example Data:
My data usually comes in like this (This is a simplified form , but the data has varying depths as shown here):
{id:115,
departments: [{
department_id:1,
department_name:"asd"}],
name: 'Test project',
}
Lets say the user decides to add in a department to the object, i wish to be able to detect the changes this way:
changes = ['departments']
or if the user changes the name :
changes = ['name']
the additional challenge here is that i wish to use this function across my forms , which means that the comparing should be able to handle different keys and depths of data
Edit:
data1 :
creation_date: "2020-06-16"
customer_information: Array(1)
0: 1
project_status: 1
sales_department: 1
sales_project_name: "helloss2sasdssssssssssss"
userProfile: Array(2)
0: 1
data2:
creation_date: "2020-06-16"
customer_information: Array(1)
0: 1
project_status: 1
sales_department: 1
sales_project_name: "helloss2"
userProfile: Array(2)
0: 1
1: 2
Function called here :
const data1 = action.original
const data2 = action.final
const difference = Object.keys(data1).filter((key)=>!walk(data1[key],data2[key]))
console.log(difference)
Here is the console log for difference :
[]
Expected:
['userProfile' , 'sales_project_name']
Simple naive recursive function walk that deep equals and returns if the branch has changes. filters keys that match.
data1 = {
creation_date: "2020-06-16",
customer_information: [1],
project_status: 1,
sales_department: 1,
sales_project_name: "helloss2sasdssssssssssss",
userProfile: [1],
version: 1
}
data2 = {
creation_date: "2020-06-16",
customer_information: [1],
project_status: 1,
sales_department: 1,
sales_project_name: "helloss2",
userProfile: [1, 2],
version: 2
}
walk = (node1, node2) => {
// different types, return false
if (typeof node1 !== typeof node2) return false
if (node1 && node2 && typeof node1 === 'object') {
const keys = Object.keys(node1)
// if type object, check same number of keys and walk on node1, node2
return keys.length === Object.keys(node2).length &&
keys.every(k => walk(node1[k], node2[k]))
}
// not object and types are same, return if node1 is equal to node2
return node1 === node2
}
console.log(
Object.keys(data1).filter((key) => !walk(data1[key], data2[key]))
)
If you don't want to use any library for comparing nested objects, you could simply convert to JSON and compare the strings.
Assuming you want to compare objects, it could look like this:
function getUnequalKeys(object1, object2) {
let unequalKeys = [];
for (let key in object1) {
if (object1.hasOwnProperty(key)
&& (
!object2.hasOwnProperty(key)
|| JSON.stringify(object1[key]) !== JSON.stringify(object2[key])
)
) {
unequalKeys.push(key);
}
}
for (let key2 in object2) {
if (object2.hasOwnProperty(key2) && !object1.hasOwnProperty(key2)) {
unequalKeys.push(key2);
}
}
return unequalKeys;
}
This would return all first-level keys that don't exist in both objects or have different values.
EDIT:
What it essentially does is the following:
Loop through each key in object1. Check if that same key exists in object2. If it does not exist, it means the key is not equal, so the condition is true and the key is added to the list of unequal keys. If the key does exist in object2, make a JSON string of both values and compare those strings. If the strings are not the same, it means they have different values. In that case, also add the key to the array of unequal keys.
Now we already checked all keys of object1.
As a last step, go through all keys of object2 and check if they are not present in object1, and in that case also add them to the array of unequal keys.
I have a set of JSON data stored in an array. The JSON looks like this:
{
"id": "1",
"key": "2"
}
and I'm trying to sum all of the "key" values inside the array of JSON strings with a for/in loop.
var total = 0;
for (var object in array) {
total += object.value;
}
The expected output is 3. However, this arrangement seems incorrect. I'm working in Node.js. Can anyone point me in the right direction?
If we have an array looking like this:
var array = [{id: "one", key: 2}, {id: "two", key: 8}]
You can simply get the total like that:
var total = array.reduce((x,y) => x + y.key, 0)
However, if you have a JSON string, where the values are also strings (like [{"id":"one","key":"2"},{"id":"two","key":"8"}]'), then you need to parse the JSON first and parse the values as numbers:
JSON.parse(array).reduce((x,y) => x + Number.parseFloat(y.key), 0)
What you have is not an array of objects, but one object with several properties.
You can use Object.keys() to get the properties as an array, then map to retrieve the values for each of those properties, and finally reduce on that array to calculate the sum:
const obj = {
"id": "1",
"key": "2"
}
const total = Object.keys(obj) // Get keys
.map( key => +obj[key] ) // Get values as numbers
.reduce ( (a,b) => a+b ); // sum up
console.log(total);
I have and array which contains more then 10 000 values and somehow lodash method includes stopped working.
The example of array:
['888888111118888',
'7771117717717771']
And my method (not working) but were working yesterday as well (with lower amount of values in array)
toFind = '7771117717717771'; // this is just for example
return _.includes(arr, toFind);
and no matter if the toFind is in array the method returns "false". Any suggestions?
EDIT
so this is what I have noticed now:
console.log(data.memberList.members[0].steamID64[7]);
toFind = data.memberList.members[0].steamID64[7];
console.log(_.findIndex(data.memberList.members[0].steamID64, toFind));
and it responds with:
999999999999
-1
so how is this even possible?
Example of Array.prototype.findIndex:
let arr = [ "123", "456" ];
let index = arr.findIndex ( x => { return x === "123" } );
This will return 0 (the first index of "123"). If you have objects:
let arr = [ { val : "123" }, { val : "456" } ];
let index = arr.findIndex ( x => { return x.val === "123" } );
And so on. If you get -1, either your matcher is wrong, or it's not in the array.
I have tremendous respect for lodash, but as we get increasing native capability such as maps, sets, along with other functional higher order capabilities (filter, map, reduce, findIndex, etc), I've found my use of it diminishing.
Array.prototype.find
let result = arr.find(r => r ==='7771117717717771');
If result is defined then it exists in the array. If you are looking for an operation that runs faster than O(n) time, you should look into alternative data structures such as maps or trees
I have a bit of a challenge. I am working on a physics application with javascript. The two main objects being used are
var force = new Object();
var torque = new Object();
with properties
force.magnitude = newArray();
force.lengthfromorigin = new Array();
force.count;
torque.lengthfromorigin= new Array();
torque.count;
now, I'd like to sort these two objects into an array based on their respective lengthfromorigins
Example: force.lengthfromorigin = [5,8] and torque.lengthfromorigin=[2,6]
so their order in this newArray would be [ torque[0], force[0], torque[1], force[1] ]
My question is it possible to have an array of different objects sorted by their respective properties, and to then use this array in a function which will make decisions based on which object is at the index. Also will I need to have an id property in each respective object to identify if the object is a torque or force.
Example:
if(newArray[i] == torque)
//do stuff
else
//do other stuff.
Something like this perhaps?
Let me explain the algorithm:
Create a new array let it be called A.
For each objects in objects:
2.1 Let the current object be called obj.
2.2 Use map to generate a new array called tuples of [obj, num] tuples
for each lengthFromOrigin numbers of obj.
3.3 Push all items of tuples into A.
Sort A on tuple[1] (which is the number) ascending.
var objects = [
{ type: 'force', lengthFromOrigin: [5, 8] },
{ type: 'torque', lengthFromOrigin: [2, 6] }
],
sorted = objects.reduce(function (arr, obj) {
arr.push.apply(arr, obj.lengthFromOrigin.map(function (num) {
return [obj, num];
}));
return arr;
}, []).sort(function (a, b) {
return a[1] - b[1];
});
console.log(sorted);
Then you can loop over sorted and easily identify if it's a torque or force by looking at the first element in the tuple.
sorted.forEach(function (tuple) {
console.log(tuple[0].type, tuple[1]);
});
//torque 2
//force 5
//torque 6
//force 8
The answer is Yes,
But you have to identify each object before you access their properties. In your case Both of the objects have a common property called lengthfromorigin which can be used to sort them properly.
To identify each object you can use a property like ID or Name.
if(Mydata[i].Name = 'torque'){
//your code goes here
}
else if(Mydata[i].Name = 'force'){
//your code goes here
}
Hope this will help you
I have a really simple Json array and I need to get back
the number of items within the array.
the list of entries in order of the id.
The array is as follows:
{"error":false,"error_msg":"","body":
{"records":[{"name":"Application","id":1},
{"name":"Fees Paid","id":2},
{"name":"Evidence Verification","id":3},
{"name":"Details QA","id":4},
{"name":"Grade Approval","id":5},
{"name":"Welcome Pack","id":6}]
},
"validation_errors":[]}
Assuming you have JSON.parsed your string into a variable called jsonobj, the following statements get the data you want:
var len = jsonobj.body.records.length;
jsonobj.body.records.sort(function(a,b) {return a.id-b.id;});
// now iterate through jsonobj.body.records and they will be in ascending ID order
Say you have your Object held in variable jObj, clone the Array/Objects so you preserve the originals, sort it as desired then return an Array which just holds the name properties.
jObj['body']['records']
.map(function (e) {return {'id': e['id'], 'name': e['name']};}) // clone
.sort(function (a, b) {return +a['id'] - +b['id'];}) // sort asc
.map(function (e) {return e['name'];}); // get names
/* [
"Application", "Fees Paid", "Evidence Verification",
"Details QA", "Grade Approval", "Welcome Pack"
] */