Sort object properties by name like another array - javascript

how can I sort object properties by name using another array as refer?
var json = '{"b":90,"c":42, "a":34}';
var obj = JSON.parse(json);
var sorting = ["a","b","c"];
I would like to have obj properties ordered just like sorting array
Thank you
Bye

var sorting = Object.keys(obj).sort();

Javascript objects are not ordered. So, you cannot actually sort them.

Why not just iterating over the array, and then access obj properties ?
for ( var i = 0; i < sorting.length; ++i ) {
var current = obj[ sorting[ i ] ];
// other stuff here...
}
If you don't intent to iterate over the obj, please explain your actual needs.

Convert Object to Array
var jsonArray = [];
$.each(myObj, function(i,n) {
jsonArray.push(n);
});
Sort Array
var jsonArraySort = jsonArray.sort();
Convert Array to Object
var jsonSort = {};
for(var i = 0; i < jsonArraySort.length; i++) {
jsonSort[i] = jsonArraySort[i];
}

You could try something like:
var sorted = []
for (i = 0; i < sorting.length; i++) {
if (json.hasOwnProperty(sorting[i])) {
sorted.push(json[sorting[i]);
}
}
/* sorted will equal [34, 90, 42] */

You cannot order the keys of an object, as per definition,
An ECMAScript object is an unordered collection of propertiesES3 Specs
The mechanics and order of enumerating the properties (step 6.a in the first algorithm, step 7.a in the second) is not specified.
Properties of the object being enumerated may be deleted during enumeration. If a property that has not yet been visited during enumeration is deleted, then it will not be visited. If new properties are added to the object being enumerated during enumeration, the newly added properties are not guaranteed to be visited in the active enumeration. A property name must not be visited more than once in any enumeration.ES5 Specs
If you want to a sorted array consisting of your objects keys, you can use [Object.keys][4], To get an array of them, which you can then sort.
var obj = {b:90,c:42, a:34}
console.log (
Object.keys (obj).sort ()
) // ["a","b","c"]
If you are interested in a sorted array, containing both, keys and values, you could do the following.
var obj = {b: 90, c: 42, a: 34},
srt = Object.keys(obj).sort().map(function (prop) {
return {
key: prop,
value: obj[prop]
}
});
console.log(srt) //[{"key":"a","value":34},{"key":"b","value":90},{"key":"c","value":42}]

Related

JS- How to convert an array with key and value pairs to an object?

var arr = [];
arr['k1'] = 100;
console.log(arr); //o/p - [k1: 100]
arr.length; //o/p - 0
window.copy(arr); //copies: []
I want to convert this array-like object to a proper obj i.e,
arr = { k1: 100}
So doing window.copy(arr) should copy {k1:100}
NOTE- I need to do this as Node.js express server returns empty arrays in response for such cases.
You can use object spread syntax to copy all own enumerable properties from the original object to a new object:
const arr = [];
arr['k1'] = 100;
const obj = { ...arr };
console.log(obj);
This works even if arr is originally an array, rather than a plain object, because the k1 property exists directly on the array.
(But ideally, one should never have code that assigns to arbitrary properties of an array - better to refactor it to use an object in such a situation to begin with)
var array = []
array["k1"] = 100;
var newObject = Object.assign({},array);
console.log(newObject);

Length property not updating on object arrays

Two problems consider the following object:
//new obj
var obj = {};
obj['cars'] = [];
obj['cars']['toyota'] = 1;
obj['cars']['mazda'] = 0;
console.log(obj);
console.log(JSON.stringify(obj));
Why does my cars array have length of 0? Do i have to update the length property manually?
Why is my stringified object empty when it has parameters in it i'm assuming it is tied into the length property?
Fiddle:https://jsfiddle.net/wcd7f8Lz/
car is initialized as an array, but used as an Object. and an object does not have length attribute...
To get the length of an object, you can do ̀̀̀̀Object.keys(obj).length (get the keys list, and because it is an array, it have a length).
But the problem is also that you initialize cars as an array, but use it as Object...
see docs here:
http://www.w3schools.com/js/js_arrays.asp
http://www.w3schools.com/js/js_objects.asp
The solution is to initialize it as Object:
//new obj
var obj = {};
obj['cars'] = {}; //And other object
obj['cars']['toyota'] = 1;
obj['cars']['mazda'] = 0;
console.log(obj);
console.log(JSON.stringify(obj));
But if you want instead a simple array:
//new obj
var obj = {};
obj['cars'] = [];
obj['cars'][1] = "toyota";
obj['cars'][0] = "mazda";
console.log(obj);
console.log(JSON.stringify(obj));
The syntax is ̀array[identifier] = value;
(and not ̀̀̀̀̀array[value] = identifier)
I've updated the fiddle.
obj.cars.length is 0, because you don't push new items in array, but change it properties:
var obj = {};
obj.cars = []; // obj.cars is empty array
obj.cars.toyota = 1; // obj.cars is empty array with a new property toyota
obj.cars.push('mazda'); // obj.cars is array with a new property toyota and one element mazda
console.log(obj.cars instanceof Array,
obj.cars.length,
Object.keys(obj.cars)); // output: true 1 ["toyota"]
Why you don't use it in this way?
var cars = [];
cars.push({name:'toyota', value:1});
cars.push({name:'mazda', value:0})
That's because you aren't using an array (despite declaring it with an array literal), you're using it as an object.
Arrays are just a special case of object, meaning they can have individual properties. These properties don't exist "in" the array but instead are properties "of" the array.
var arr = [1, 2, 3];
arr.thing = 'a';
console.log(arr.length); // 3
To add elements to an array, you should use push:
var arr = []; // length: 0
arr.push(1); // length: 1
If you want to be able to access an object both by name and index then you can combine push with custom properties.
var arr = [];
arr.push(0);
arr.mazda = 0;

Convert Array of Javascript Objects to single simple array

I have not been able to figure out how to properly accomplish this.
I have a JS array of objects that looks like this:
[{"num":"09599","name":"KCC","id":null},{"num":"000027","name":"Johns","id":null}]
I would like to convert this into a simple, single JS array, without any of the keys, it should look like this:
[
"09599",
"KCC",
"000027",
"Johns" ]
The IDs can be dropped entirely. Any help would be really appreciated.
Simply iterate the original array, pick the interesting keys and accumulate them in another array, like this
var keys = ['num', 'name'],
result = [];
for (var i = 0; i < data.length; i += 1) {
// Get the current object to be processed
var currentObject = data[i];
for (var j = 0; j < keys.length; j += 1) {
// Get the current key to be picked from the object
var currentKey = keys[j];
// Get the value corresponding to the key from the object and
// push it to the array
result.push(currentObject[currentKey]);
}
}
console.log(result);
// [ '09599', 'KCC', '000027', 'Johns' ]
Here, data is the original array in the question. keys is an array of keys which you like to extract from the objects.
If you want to do this purely with functional programming technique, then you can use Array.prototype.reduce, Array.prototype.concat and Array.prototype.map, like this
var keys = ['num', 'name'];
console.log(data.reduce(function (result, currentObject) {
return result.concat(keys.map(function (currentKey) {
return currentObject[currentKey];
}));
}, []));
// [ '09599', 'KCC', '000027', 'Johns' ]
You can use Object.keys() and .forEach() method to iterate through your array of object, and use .map() to build your filtered array.
var array = [{"num":"09599","name":"KCC","id":null},{"num":"000027","name":"Johns","id":null}];
var filtered = array.map(function(elm){
var tmp = [];
//Loop over keys of object elm
Object.keys(elm).forEach(function(value){
//If key not equal to id
value !== 'id'
//Push element to temporary array
? tmp.push(elm[value])
//otherwise, do nothing
: false
});
//return our array
return tmp;
});
//Flat our filtered array
filtered = [].concat.apply([], filtered);
console.log(filtered);
//["09599", "KCC", "000027", "Johns"]
How about using map :
var data = [
{"num":"09599","name":"KCC","id":null}
{"num":"000027","name":"Johns","id":null}
];
var result = data.map(function(obj) {
return [
obj.num,
obj.name,
obj.id
];
});

Sort javascript key/value pairs inside object

I have some problem with sorting items inside object. So I have something like this:
var someObject = {
'type1': 'abc',
'type2': 'gty',
'type3': 'qwe',
'type4': 'bbvdd',
'type5': 'zxczvdf'
};
I want to sort someObject by value, and this is where I have problem.
I have sorting function that should return key/value pairs sorted by value:
function SortObject(passedObject) {
var values = [];
var sorted_obj = {};
for (var key in passedObject) {
if (passedObject.hasOwnProperty(key)) {
values.push(passedObject[key]);
}
}
// sort keys
values.sort();
// create new object based on Sorted Keys
jQuery.each(values, function (i, value) {
var key = GetKey(passedObject, value);
sorted_obj[key] = value;
});
return sorted_obj;
}
and function to get key:
function GetKey(someObject, value) {
for (var key in someObject) {
if (someObject[key] === value) {
return key;
}
}
}
The problem is in last part when creating new, returning object - it's sorted by key again. Why? And this is specific situation when i have to operate on object NOT on array (yes I know that would be easier...)
Does anyone know how to sort items in object?
Plain objects don't have order at all. Arrays -that are a special types of objects- have.
The most close thing that you can have is an array with the object values sorted . Something like, for example:
_valuesOfAnObjectSorted = Object.keys(object).map(function(k){ return object[k]; }).sort();
You have two possibilities:
Refactor your object into an array
Something like this:
var myObj = [
['type1', 'abc'],
['type2', 'gty'],
...
];
Or even better, since using it somewhere would not rely on array positions but full named keys:
var myObj = [
{name: 'type1', val:'abc'},
{name: 'type2', val:'gty'},
...
];
Use your object with an auxiliar array
Wherever you want to use your object ordered by the keys, you can extract the keys as an array, order it and traverse it to access the object
var ordKeys = Object.keys(myObj).sort(); // pass inside a function if you want specific order
var key;
for (var i = 0, len = ordKeys.length; i < len; i +=1) {
key = ordKeys[i]
alert(key + " - " + myObj[key]);
}
Combination of both of them
If the object is not constructed by you, but comes from somewhere else, you can use the second option approach to construct an array of objects as in the first option. That would let you use your array anywhere with perfect order.
EDIT
You might want to check the library underscore.js. There you have extremely useful methods that could do the trick pretty easily. Probably the method _.pairs with some mapping would do all the work in one statement.

Javascript data structure for fast lookup and ordered looping?

is there a data structure or a pattern in Javascript that can be used for both fast lookup (by key, as with associative arrays) and for ordered looping?
Right, now I am using object literals to store my data but I just disovered that Chrome does not maintain the order when looping over the property names.
Is there a common way to solve this in Javascript?
Thanks for any hints.
Create a data structure yourselves. Store the ordering in an array that is internal to the structure. Store the objects mapped by a key in a regular object. Let's call it OrderedMap which will have a map, an array, and four basic methods.
OrderedMap
map
_array
set(key, value)
get(key)
remove(key)
forEach(fn)
function OrderedMap() {
this.map = {};
this._array = [];
}
When inserting an element, add it to the array at the desired position as well as to the object. Insertion by index or at the end is in O(1).
OrderedMap.prototype.set = function(key, value) {
// key already exists, replace value
if(key in this.map) {
this.map[key] = value;
}
// insert new key and value
else {
this._array.push(key);
this.map[key] = value;
}
};
When deleting an object, remove it from the array and the object. If deleting by a key or a value, complexity is O(n) since you will need to traverse the internal array that maintains ordering. When deleting by index, complexity is O(1) since you have direct access to the value in both the array and the object.
OrderedMap.prototype.remove = function(key) {
var index = this._array.indexOf(key);
if(index == -1) {
throw new Error('key does not exist');
}
this._array.splice(index, 1);
delete this.map[key];
};
Lookups will be in O(1). Retrieve the value by key from the associative array (object).
OrderedMap.prototype.get = function(key) {
return this.map[key];
};
Traversal will be ordered and can use either of the approaches. When ordered traversal is required, create an array with the objects (values only) and return it. Being an array, it would not support keyed access. The other option is to ask the client to provide a callback function that should be applied to each object in the array.
OrderedMap.prototype.forEach = function(f) {
var key, value;
for(var i = 0; i < this._array.length; i++) {
key = this._array[i];
value = this.map[key];
f(key, value);
}
};
See Google's implementation of a LinkedMap from the Closure Library for documentation and source for such a class.
The only instance in which Chrome doesn't maintain the order of keys in an object literal seems to be if the keys are numeric.
var properties = ["damsonplum", "9", "banana", "1", "apple", "cherry", "342"];
var objLiteral = {
damsonplum: new Date(),
"9": "nine",
banana: [1,2,3],
"1": "one",
apple: /.*/,
cherry: {a: 3, b: true},
"342": "three hundred forty-two"
}
function load() {
var literalKeyOrder = [];
for (var key in objLiteral) {
literalKeyOrder.push(key);
}
var incremental = {};
for (var i = 0, prop; prop = properties[i]; i++) {
incremental[prop] = objLiteral[prop];
}
var incrementalKeyOrder = [];
for (var key in incremental) {
incrementalKeyOrder.push(key);
}
alert("Expected order: " + properties.join() +
"\nKey order (literal): " + literalKeyOrder.join() +
"\nKey order (incremental): " + incrementalKeyOrder.join());
}
In Chrome, the above produces: "1,9,342,damsonplum,banana,apple,cherry".
In other browsers, it produces "damsonplum,9,banana,1,apple,cherry,342".
So unless your keys are numeric, I think even in Chrome, you're safe. And if your keys are numeric, maybe just prepend them with a string.
As
has been noted, if your keys are numeric
you can prepend them with a string to preserve order.
var qy = {
_141: '256k AAC',
_22: '720p H.264 192k AAC',
_84: '720p 3D 192k AAC',
_140: '128k AAC'
};
Example

Categories

Resources