如何在javascript中实现映射或排序集

如何在javascript中实现映射或排序集,javascript,arrays,sorting,object,Javascript,Arrays,Sorting,Object,Javascript具有使用数字索引的数组[“john”、“Bob”、“Joe”],以及可以像关联数组或“maps”这样使用的对象,这些对象允许对象值的字符串键{“john”:28,“Bob”:34,“Joe”:4} 在PHP中,A)按值排序(同时维护键)和B)测试关联数组中是否存在值都很容易 $array = ["john" => 28, "bob" => 34, "joe" => 4]; asort($array); // ["joe" => 4, "john" =

Javascript具有使用数字索引的数组
[“john”、“Bob”、“Joe”]
,以及可以像关联数组或“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"]) { }

通常不会对对象进行排序。但如果你这样做了:

如果要对数组进行排序,请执行以下操作

var arraylist = [{"john" : 28},{ "bob": 34},{ "joe" : 4}];
您可以始终使用
Array.prototype.sort
函数。
来源:

也许这段代码看起来像你想要的:

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
Object.prototype.asort=function(){
var retVal={};
var self=这个;
var-keys=Object.keys(这个);
keys=keys.sort(函数(a,b){返回self[a]-self[b]});
对于(变量i=0;i
看一下,我想我可能已经找到了一个更好的方法,通过扩展对象来处理这个问题。原型:

// 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);
//保留索引时按值排序
Object.prototype.iterateSorted=函数(工作者,限制)
{
var keys=Object.keys(this),self=this;
排序(函数(a,b){return self[b]-self[a]});
如果(限制){
limit=数学最小值(key.length,limit);
}
limit=limit | | keys.length;
对于(变量i=0;i

如果您使用开源项目,它会很容易


我不知道为什么这些答案都没有提到内置JS类的存在。似乎是一个ES6的补充,也许这就是原因

理想情况下,覆盖下面的
添加
。。。NB重写
甚至不需要访问
对象的原型。当然,您可以为整个
集合
类重写这些方法。或者创建一个子类,
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.三,

NB
Set.keys()
返回的不是
Set
中的项,而是一个迭代器。您可以选择返回排序后的数组,但这显然违反了类的“约定”

要覆盖哪一个?取决于您的使用情况和
集合的大小。如果同时重写这两个选项,则将复制排序活动,但在大多数情况下,这可能无关紧要

注意:我建议的
add
函数当然是幼稚的,是一个“初稿”:每次
add
时重建整个集合可能会非常昂贵。通过检查
集合中的现有元素,并使用比较函数、二叉树结构*,或其他方法来确定中的位置,从而添加要添加的候选项(我称之为“候选项”,因为如果“相同”则会被拒绝)元素(即元素本身)已被发现存在)

问题还询问了排序地图的类似安排。。。事实上,ES6有一个新的类别,它适合于类似的处理。。。而且,
Set
只是一个专门的
Map
,正如您所期望的那样


*例如,

使用ES6,您可以选择使用采用可选比较函数的
sort
方法扩展
Map
构造函数/类(就像数组一样)。该
sort
方法将采用两个参数,每个参数都是键/值对,因此可以对键或值(或两者)进行排序

sort
方法将依赖于以插入顺序迭代条目的映射的记录行为。因此,这个新方法将根据排序顺序访问条目,然后删除并立即重新插入它们

下面是它的样子:

类SortableMap扩展了Map{
排序(cmp=(a,b)=>a[0]。本地比较(b[0])){
for[…this.entries()]排序(cmp)的常量[key,value]{
删除(键);
this.set(key,value);//在订单末尾添加新的键
}
}
}
//演示
const mp=新的可排序地图([[3,“三”],[1,“一”],[2,“两”]);
console.log(“Before:”,JSON.stringify([…mp]);//之前
mp.sort((a,b)=>a[0]-b[0]);//自定义比较功能:对数字键进行排序

console.log(“After:,JSON.stringify([…mp]);//下面是OrderedMap的一个实现。 使用函数
get()
set()
提取键值对或将键值对推送到
OrderedMap
。 它在内部使用数组来维护顺序。
类OrderedMap{
构造函数(){
this.arr=[];
归还这个;
}
获取(键){

对于(让i=0;如果你想使用的第一行是:Object.keys一旦你有了键和值,你就有了对象。对象没有被排序。但这非常鼓舞人心:@Wikunia,谢谢。我更新了代码。你想按键或值排序吗?因为你的js脚本是按键排序的,而你的php是按值排序的。答案是对象是无序的。您的解决方案是错误的。您不能在javascript中返回已排序的对象,因为标准ES5在迭代对象属性时不能保证顺序。只需保留
mySet.add( 3 ); mySet.add( 2 ); mySet.add( 1 ); mySet.add( 2 );
for( let item of mySet.keys() ){ console.log( item ) };