i want to sort the keys or name of the method.. following is the object http://pastie.org/411854
If I understand correctly, you would like to put members in order based on key or method name (which is the same value)? This has no meaning for Object since members have no order.
However, if you put these objects in an array like this:
var apiDocs = [
{
"methodName": "friendsGetByUser",
"methodDescription": "Returns user ids of friends of the specified user.",
...
}, {
"methodName": "friendsGetBestFriends",
"methodDescription": "Returns user ids of best friends of the logged in user.",
...
}
...
];
Then you can sort the array easily by invoking Array.sort passing in compare function.
apiDocs.sort(function (a, b) {
return a.methodName < b.methodName;
});
To get a sorted array of the function names you could use the following:
var functions = [];
for(functionName in apiDocs) {
functions.push(functionName);
}
functions.sort();
If you want to perform some sort of more complex sort you could do something along the lines of
var functions = [];
for(functionName in apiDocs) {
functions.push(apiDocs[functionName]);
}
functions.sort(//put sorting closure here)
You can get more information about custom sorting here: Array Sorting Explained
Related
In my project I had to convert a Javascript Object into a Map object called mapResults. After some transformations (slicing out the first two values) I now want to iterate over this collection to render some list items with the following syntax.
{key1}:{value1}
{key2}:{value2}
The thing is that I also have an array called resultsKey with strings that I want to use as {keys} for every list item. So, lets say that my Map object and my strings array look like this:
mapResults =
0: gameStatus -> "You Won!"
1: difficulty -> "Intermediate"
2: movesCount -> 13
resultsKey = [
"Final result",
"Level",
"Number of movements",
]
Now I would like to iterate over both collections to get the desired list item output as:
Final result : You Won!
Where every key of the list item its taken from my resultsKey array and every value is taken from my mapResults object. Both collections are the same length/size.
I know that if I had an Object object (name it objectResults)instead of a Map object, I could achieve this by calling Object.keys() on the Object, and then calling .map() or forEach() on the resulting array (lets call it objectResultsKeys) like this:
objectResultsKeys.map((key, index)=>{
return <li>
{resultsKey[index]}:{objectResults[key]}
</li>
})
The thing here is, that if I had this situation I would be able to use the index parameter that the .map() function provides to access the resultsKey strings array and obtain the value I want. But there is no such thing when it comes to iterating over Map objects.
So what I want to know is if there is any solution that provides me with and index value that I can use to access my strings array while iterating over the Map object. Or if there is any other solution to achieve a similar outcome to what I've explained. Im constrained to use a Map object for this solution.
You could just take a counter:
let index = 0;
for(const [key, value] of map.entries()) {
// ...
index++;
}
Or you turn the entries into an array:
[...map.entries()].forEach(([key, value], index) =>
//...
);
But actually as Maps are ordered by insertion time I would not rely on the Maps order.
This question already has answers here:
Sort Keys in Javascript Object
(2 answers)
Closed 2 years ago.
I have an object
{
"William_Hill":{},
"bet365":{},
"royal panda":{"pay":0},
"karamba":{"roller":0,"braned":0,"pay":0},
"betfred":{"braned":0}
}
and want to sort it by the nuber of properties, so the result shoul look like this and it must be an object
{
"William_Hill":{},
"bet365":{},
"betfred":{"braned":0},
"royal panda":{"pay":0},
"karamba":{"roller":0,"braned":0,"pay":0}
}
I have sorted it like this one but the result is an array
var keysSorted = Object.keys(resultArray).sort(function(a,b){
return Object.keys(resultArray[a]).length-Object.keys(resultArray[b]).length;
});
Until ES2015, JavaScript object properties had no defined order. They do now, but that order isn't respected by for-in or Object.keys, only by new features like Object.getOwnPropertyNames. It's also more complicated than it seems and of very limited use.
There's almost never any good reason to try to put an object in a specific order. If you want order, use an array, or in ES2015 use a Map (see below).
But that said, in ES2015, with property names like yours, it's possible: The only way to set the order of the properties in an object is to determine the order in which they're created, which (for properties that aren't array indexes) is the order they'll be in. So you can do this by getting all the property names, determining the order you want them in, and then creating a new object, adding the properties in that order.
Beware, though, that certain classes of property names (what we call "array indexes") are sorted differently. None of your property names meets the definition, but (say) "123" would.
Here's an example of doing it, if you really want to (I've happily used ES2015's arrow functions, since this only works in ES2015):
// The object
let obj = {
"William_Hill":{},
"bet365":{},
"royal panda":{"pay":0},
"karamba":{"roller":0,"braned":0,"pay":0},
"betfred":{"braned":0}
};
// Get its names, sort them by how may sub-props there are
let names = Object.keys(obj);
names.sort((a, b) => Object.keys(obj[a]).length - Object.keys(obj[b]).length);
// Get the new object
let newObj = names.reduce((acc, name) => {
acc[name] = obj[name];
return acc;
}, {});
// Show its property names
console.log(Object.getOwnPropertyNames(newObj));
Naturally, that can be shorter, I've kept the steps separate for clarity. Similarly, I go back and forth on that use of reduce, you could do the last bit like this instead:
// Get the new object
var newObj = {};
names.forEach(name => {
acc[name] = obj[name];
});
Here's an example using a Map instead, which offers much less complicated ordering of entries (no worries about "array indexes"):
// The object
let obj = {
"William_Hill":{},
"bet365":{},
"royal panda":{"pay":0},
"karamba":{"roller":0,"braned":0,"pay":0},
"betfred":{"braned":0}
};
// Get its names, sort them by how may sub-props there are
let names = Object.keys(obj);
names.sort((a, b) => Object.keys(obj[a]).length - Object.keys(obj[b]).length);
// Get the map
let map = new Map();
names.forEach(name => {
map.set(name, obj[name]);
});
// Show its property names
console.log(Array.from(map.keys()));
Dict object in Javascript cannot guarantee the element order.
So maybe you can only use an array to handler the sorted result.
Reference: Does JavaScript Guarantee Object Property Order?
I'm sorry if this has been asked before, it's something that's difficult to search for...
I want to use a javascript Array to hold objects, with the key as the ID
for example, let's say I had a bunch of people who had different IDs
var people = new Array();
var person = {property: value}; // this is person ID 4
var people[4] = person;
I want to be able to then reference that user by saying, people[ID].propery
The problem is that the output of this array now would be;
null,null,null,null,object
Because it's expecting the keys to be 0,1,2,3,4
Am I being stupid or something? :-) We can do it for strings right, so why not non-sequential numbers?
What I'm trying to avoid is having to loop over every single object in the array every time I want to access a particular person inside it, therefore I figured that using the ID number as the key would work
Thanks guys! :-)
Use a dictionary object
var people = {};
people[4] = 'me';
I'd suggest you use collections. A collection is an array of objects. You can then pass properties on each person. You can filter your collection by any property. So close to what you're doing, but instead of relaying on the index, pass the id for each person.
var people = []; // a collection
var person = {
id: 4,
name: 'John'
};
people.push(person);
// Filtering:
// By id
var john = people.filter(function(person) {
return person.id == 4;
});
// By name
var john = people.filter(function(person) {
return person.name == 'John';
});
You can abstract those loops above to re-use them. Also make sure your id's are unique. If data is coming from the DB it should be OK, otherwise I'd keep track of them somewhere.
The advantage of collections, as opposed to a plain object with keys is that you can sort and filter, while an object, where the order of properties is not guaranteed, you can't do it as simple.
Note that filter only works on "modern browsers", so IE9+, but there are polyfills for older browsers.
when we use a string as key, like this:
var people = {}; //this is an object
people[name] = 'toto';
we are adding new property to this object, because each object in javascript can be seen as a hashtable.
If you use an array, it's still an object, you can add properties to it using string as key. But if you do something like people[4] = 'toto';, you are adding a string to the array, the length of the array will then become 5. Of course the number 4 will still be a property of this array object.
Example
Link: http://jsfiddle.net/ewBGt/
var test = [{
"name": "John Doo"
}, {
"name": "Foo Bar"
}]
var find = 'John Doo'
console.log(test.indexOf(find)) // output: -1
console.log(test[find]) // output: undefined
$.each(test, function(index, object) {
if(test[index].name === find)
console.log(test[index]) // problem: this way is slow
})
Problem
In the above example I have an array with objects. I need to find the object that has name = 'John Doo'
My .each loop is working, but this part will be executed 100 times and test will contain lot more objects. So I think this way will be slow.
The indexOf() won't work because I cannot search for the name in object.
Question
How can I search for the object with name = 'John Doo' in my current array?
jQuery $.grep (or other filtering function) is not the optimal solution.
The $.grep function will loop through all the elements of the array, even if the searched object has been already found during the loop.
From jQuery grep documentation :
The $.grep() method removes items from an array as necessary so that
all remaining items pass a provided test. The test is a function that
is passed an array item and the index of the item within the array.
Only if the test returns true will the item be in the result array.
Provided that your array is not sorted, nothing can beat this:
var getObjectByName = function(name, array) {
// (!) Cache the array length in a variable
for (var i = 0, len = test.length; i < len; i++) {
if (test[i].name === name)
return test[i]; // Return as soon as the object is found
}
return null; // The searched object was not found
}
I have done sometimes "searchable map-object" in this kind of situation. If the array itself is static, you can transform in to a map, where array values can be keys and map values indexes. I assume values to be unique as in your example.
Lo-Dash (www.lodash.com) has create selection of utils for easily looping etc. Check it out!
Note: But often you really don't have to worry about looping trough array with 100 elements.
If you just want to find out if the value is there, you can use lodash's includes function like this:
var find = 'John Doo'
[{ "name": "John Doo" }, { "name": "Foo Bar" }].some(function (hash) {
if (_.includes(hash, find)) return true;
});
Documentation:
_.includes()
Array.prototype.some()
Perhaps you should use the $.grep functionality in jQuery:
var test = [{
"name": "John Doo"
}, {
"name": "Foo Bar"
}]
var find = 'John Doo'
var found = $.grep(test, function(obj){
return obj['name'] == find;
});
console.log(found);
Fiddle: http://jsfiddle.net/ewBGt/3/
The only thing you can possibly do is use build-in array methods (if available) in preference over doing the looping yourself – the filter method would be applicable here.
But I expect that JS libraries like jQuery used by sbeliv01 in his answer already check for that internally (and provide a fallback solution if these array methods are not available natively) – so don’t expect a massive performance boost.
Is there a way to do this out of the box with the _.sortBy method or any other part of the library?
You mean like this?
var array = [
{ name: "banana" },
{ name: "carrot" },
{ name: "apple" }
];
var sorted = _(array).sortBy("name");
I'd say it works out of the box.
If you wanted to sort an ordinary array of strings, you probably just want to use sort:
var flatArray = ["banana", "carrot", "apple"];
flatArray.sort();
See here. Also works.
Note that Underscore's sortBy returns a new array which is sorted, where JavaScript's built-in sort function sorts an array in place.
Since you tagged your question with the backbone.js tag, I'm assuming you mean to sort a collection, you just need to provide a comparator function on your collection and backbone will keep the collection sorted.
If your question is specifically alphabeticical sorting, I believe that is the default sort, from the backbone.js documentation (I linked to it above)
chapters.comparator = function(chapter) {
return chapter.get("page");
};