Javascript包含使用数字索引["john", "Bob", "Joe"]
的数组和可以像关联数组一样使用的对象或者#34; maps"允许对象值{"john" : 28, "bob": 34, "joe" : 4}
的字符串键。
在PHP中,很容易 A)按值排序(同时保持键)和 B)测试关联数组中是否存在值。
$array = ["john" => 28, "bob" => 34, "joe" => 4];
asort($array); // ["joe" => 4, "john" => 28, "bob" => 34];
if(isset($array["will"])) { }
您如何在Javascript中实现此功能?
这是加权列表或有序集合等常见需求,您需要在数据结构中保留一个值的副本(如标记名称),并保留加权值。
这是我迄今为止最好的:
function getSortedKeys(obj) {
var keys = Object.keys(obj);
keys = keys.sort(function(a,b){return obj[a]-obj[b]});
var map = {};
for (var i = keys.length - 1; i >= 0; i--) {
map[keys[i]] = obj[keys[i]];
};
return map;
}
var list = {"john" : 28, "bob": 34, "joe" : 4};
list = getSortedKeys(list);
if(list["will"]) { }
答案 0 :(得分:1)
关注this answer by Luke Schafer我想我可能已经找到了一种更好的方法来扩展Object.prototype来处理这个问题:
// Sort by value while keeping index
Object.prototype.iterateSorted = function(worker, limit)
{
var keys = Object.keys(this), self = this;
keys.sort(function(a,b){return self[b] - self[a]});
if(limit) {
limit = Math.min(keys.length, limit);
}
limit = limit || keys.length;
for (var i = 0; i < limit; i++) {
worker(keys[i], this[keys[i]]);
}
};
var myObj = { e:5, c:3, a:1, b:2, d:4, z:1};
myObj.iterateSorted(function(key, value) {
console.log("key", key, "value", value)
}, 3);
答案 1 :(得分:1)
使用ES6,您可以选择使用Map
方法扩展sort
构造函数/类,该方法采用可选的比较函数(就像数组一样)。 sort
方法将采用两个参数,每个参数都是键/值对,以便排序可以在键或值(或两者)上发生。
sort
方法将依赖于Google的记录行为,即按插入顺序迭代条目。因此,这个新方法将根据排序顺序访问条目,然后删除并立即重新插入它们。
以下是这样的看法:
class SortableMap extends Map {
sort(cmp = (a, b) => a[0].localeCompare(b[0])) {
for (const [key, value] of [...this.entries()].sort(cmp)) {
this.delete(key);
this.set(key, value); // New keys are added at the end of the order
}
}
}
// Demo
const mp = new SortableMap([[3, "three"],[1, "one"],[2, "two"]]);
console.log("Before: ", JSON.stringify([...mp])); // Before
mp.sort( (a, b) => a[0] - b[0] ); // Custom compare function: sort numerical keys
console.log(" After: ", JSON.stringify([...mp])); // After
答案 2 :(得分:0)
您通常不会对对象进行排序。但如果你这样做:Sorting JavaScript Object by property value
如果要对数组进行排序,请说明以下内容
var arraylist = [{"john" : 28},{ "bob": 34},{ "joe" : 4}];
您始终可以使用Array.prototype.sort
功能。
资料来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
答案 3 :(得分:0)
也许这段代码看起来像你想要的那样:
Object.prototype.asort = function(){
var retVal = {};
var self = this;
var keys = Object.keys(this);
keys = keys.sort(function(a,b){return self[a] - self[b]});
for (var i = 0; i < keys.length; i++) {
retVal[keys[i]] = this[keys[i]];
}
return retVal;
}
var map = {"john" : 28, "bob": 34, "joe" : 4}
var sortedMap = map.asort();//sortedMap["will"]: undefined
答案 4 :(得分:0)
如果您使用开源项目jinqJs那么简单。
请参阅Fiddler
var result = jinqJs()
.from([{"john" : 28},{ "bob": 34},{ "joe" : 4}])
.orderBy([{field: 0}])
.select();
答案 5 :(得分:0)
我不确定为什么这些答案都没有提到内置JS类Set的存在。似乎是ES6的补充,也许这就是原因。
理想情况下覆盖以下add
或 keys
...覆盖keys
的NB甚至不需要访问Set
对象的原型。当然,您可以为整个Set
类覆盖这些方法。或者创建一个子类SortedSet
。
const mySet = new Set();
const mySetProto = Object.getPrototypeOf( mySet );
const addOverride = function( newObj ){
const arr = Array.from( this );
arr.add( newObj );
arr.sort(); // or arr.sort( function( a, b )... )
this.clear();
for( let item of arr ){
mySetProto.add.call( this, item );
}
}
mySet.add = addOverride;
const keysOverride = function(){
const arr = Array.from( this );
arr.sort(); // or arr.sort( function( a, b )... )
return arr[Symbol.iterator]();
}
mySet.keys = keysOverride;
用法:
mySet.add( 3 ); mySet.add( 2 ); mySet.add( 1 ); mySet.add( 2 );
for( let item of mySet.keys() ){ console.log( item ) };
打印出来:
1 ... 2 ... 3
NB Set.keys()
不返回Set
中的项目,而是迭代器。您可以选择返回已排序的数组,但您显然会违反课程&#34;合同&#34;。
要覆盖哪一个?取决于您的使用情况和Set
的大小。如果你覆盖两者,你将复制排序活动,但在大多数情况下,它可能不重要。
注意我建议的add
功能当然是天真的,第一个草稿&#34;:每次add
成本非常高时重建整套。基于检查Set
中的现有元素并使用比较函数,二叉树结构*或其他方法确定其中的 where ,显然有更聪明的方法。添加候选者以进行添加(我说&#34;候选人&#34;因为如果已经发现&#34;相同的&#34;元素本身已被发现,它将被拒绝。)
这个问题还询问有关排序地图的类似安排......事实上,事实证明ES6有一个新的Map类,它有助于类似的处理...以及Set
正如您所料,它只是一个专门的Map
。
答案 6 :(得分:0)
这是OrderedMap的实现。
使用功能get()
和set()
将键值对提取或推入OrderedMap
。
它在内部使用数组维护顺序。
class OrderedMap {
constructor() {
this.arr = [];
return this;
}
get(key) {
for(let i=0;i<this.arr.length;i++) {
if(this.arr[i].key === key) {
return this.arr[i].value;
}
}
return undefined;
}
set(key, value) {
for(let i=0;i<this.arr.length;i++) {
if(this.arr[i].key === key) {
this.arr[i].value = value;
return;
}
}
this.arr.push({key, value})
}
values() {
return this.arr;
}
}
let m = new OrderedMap();
m.set('b', 60)
m.set('a', 10)
m.set('c', 20)
m.set('d', 89)
console.log(m.get('a'));
console.log(m.values());