如何防止对象数字属性的自动排序?

时间:2015-10-26 17:22:53

标签: javascript sorting object properties

为什么我遇到了这个问题: 我试图解决算法问题,我需要返回数组中出现的大部分时间的数字。像[5,4,3,2,1,1]应该返回1。 并且当两个数字同时出现最大外观返回时,第一个出现。与[5,5,2,2,1]类似,返回 5 ,因为 5 首先出现。我使用一个对象来存储每个数字的外观。关键是数字本身。

所以当输入是[5,5,2,2,1]我的对象应该是  Object {5: 2, 2: 2, 1: 1}但实际上我得到Object {1: 1, 2: 2, 5: 2} 因此,当我使用for..in迭代对象时,我返回 2 而不是 5 。这就是我问这个问题的原因。

Chrome控制台中出现此问题,我不确定这是否是一个常见问题: 当我运行以下代码时

var a = {};
a[0]=1;
a[1]=2;
a[2]=3;

a 是:Object {0: 1, 1: 2, 2: 3}

但是当我颠倒了作业的顺序时:

 var a = {};
 a[2]=3;
 a[1]=2;
 a[0]=1;

a 也是:Object {0: 1, 1: 2, 2: 3} 数字属性按升序自动排序。 我尝试了前缀或后缀数字属性,如

var a = {};
a['p'+0]=1;
a['p'+1]=2;
a['p'+2]=3;
console.log(a);//Object {p0: 1, p1: 2, p2: 3}

这保持了财产秩序。这是解决问题的最佳方法吗?反正有没有阻止这种自动排序行为?这只发生在Chrome V8 JavaScript引擎中吗?提前谢谢!

11 个答案:

答案 0 :(得分:1)

target = {}
target[' ' + key] = value // numeric key

这可以防止对象数字属性的自动排序。

答案 1 :(得分:1)

我已经用IDs键控的归一化数组迷惑了这个问题>经过研究,我发现无法修复使用对象键的方法,因为默认情况下,当您使用Java脚本时,JavaScript会使用数字对任何对象键进行排序重复它。

我已经完成并且对我有用的解决方案是放置一个“ sortIndex”字段,然后使用该字段对列表进行排序。

答案 2 :(得分:1)

这是一个古老的话题,但是仍然值得一提,因为在一分钟的谷歌搜索中很难找到直接的解释。

我最近进行了一次编码练习,发现数组中最小/最大 频繁整数的首次出现和你的情况一样

我遇到了与您相同的问题,让数字键在JavaScript对象中按ASC排序,这不保留元素的原始顺序,这是js中的默认行为。

在ES6中解决此问题的更好方法是使用一种名为Map

的新数据类型。

地图可以保留元素(对)的原始顺序,并且还具有对象带来的独特关键优势。

let map = new Map()
map.set(4, "first") // Map(1) {4 => "first"}
map.set(1, "second") // Map(2) {4 => "first", 1 => "second"}
map.set(2, "third") // Map(3) {4 => "first", 1 => "second", 2 => "third"}
for(let [key, value] of map) {
  console.log(key, value)
}
// 4 "first"
// 1 "second"
// 2 "third"

但是,使用对象数据类型也可以解决该问题,但是我们需要输入数组的帮助来恢复元素的原始顺序:

function findMostAndLeast(arr) {
  let countsMap = {};
  let mostFreq = 0;
  let leastFreq = arr.length;
  let mostFreqEl, leastFreqEl;

  for (let i = 0; i < arr.length; i++) {
    let el = arr[i];
    // Count each occurrence
    if (countsMap[el] === undefined) {
      countsMap[el] = 1;
    } else {
      countsMap[el] += 1;
    }
  }

  // Since the object is sorted by keys by default in JS, have to loop again the original array
  for (let i = 0; i < arr.length; i++) {
    const el = arr[i];

    // find the least frequent 
    if (leastFreq > countsMap[el]) {
      leastFreqEl = Number(el);
      leastFreq = countsMap[el];
    }

    // find the most frequent 
    if (countsMap[el] > mostFreq) {
      mostFreqEl = Number(el);
      mostFreq = countsMap[el];
    }
  }

  return {
    most_frequent: mostFreqEl,
    least_frequent: leastFreqEl
  }
}
const testData = [6, 1, 3, 2, 4, 7, 8, 9, 10, 4, 4, 4, 10, 1, 1, 1, 1, 6, 6, 6, 6];    
console.log(findMostAndLeast(testData)); // { most_frequent: 6, least_frequent: 3 }, it gets 6, 3 instead of 1, 2 

答案 3 :(得分:0)

而不是生成像{5: 2, 2: 2, 1: 1}

这样的对象

生成一个符合

效果的数组
[
   {key: 5, val: 2},
   {key: 2, val: 2},
   {key: 1, val: 1}
]

或...在单独的值或键中跟踪排序顺序

答案 4 :(得分:0)

在处理数字数组索引时简单地做到这一点

data      = {}
data[key] = value

答案 5 :(得分:0)

您确实不能依赖JavaScript中对象字段的顺序,但是如果出现以下情况,我建议您使用 Map ES6 / ES2015标准)您需要保留key, value对对象的顺序。请参见下面的代码段:

let myObject = new Map();
myObject.set('z', 33);
myObject.set('1', 100);
myObject.set('b', 3);

for (let [key, value] of myObject) {
  console.log(key, value);
}
// z 33
// 1 100
// b 3

答案 6 :(得分:0)

我遇到了同样的问题,经过大量搜索,我发现防止此行为的解决方案是将key作为字符串。

喜欢:

{"a": 2, "b": 2}

答案 7 :(得分:0)

  1. 您可以在JavaScript ES6中使用Map(),以保持键插入的顺序。

  2. 只是尝试用替代解决方案解决您的问题,最近喜欢练习类似leetcode的问题

function solution(arr) {
  const obj = {};
  const record = {
    value: null,
    count: 0
  };

  for (let i = 0; i < arr.length; i++) {
    let current = arr[i];
    if (!obj[current]) {
      obj[current] = 0;
    }

    obj[current]++;

    if (obj[current] > record.count) {
      record.value = current;
      record.count = obj[current];
    }
  }

  console.log("mode number: ", record.value);
  console.log("mode number count: ", record.count);
}

答案 8 :(得分:0)

Object.keys()获得的数组中保留键顺序的最简单和最佳方法是对Object键进行一点操作。

在每个键名的前面插入一个“ _”。然后运行以下代码!

myObject = {
  _a: 1,
  _1: 2,
  _2: 3
}

const myObjectRawKeysArray = Object.keys(myObject); 
console.log(myObjectRawKeysArray)
//["_a", "_1", "_2"]

const myDesiredKeysArray = myObjectRawKeysArray.map(rawKey => {return rawKey.slice(1)}); 
console.log(myDesiredKeysArray)
//["a", "1", "2"]

只需几行代码,即可在数组中获得所需的顺序。 hApPy代码:)

答案 9 :(得分:0)

为了防止 JavaScript 中对象的数字键自动排序,最好的方法是稍微调整对象键。

我们可以在每个键名前插入一个“e”,以避免键的字典序排序,并通过使用以下代码获得正确的输出切片“e”;

object_1 = {
      "3": 11,
      "2": 12,
      "1": 13
      }

let automaticSortedKeys = Object.keys(object_1);
console.log(automaticSortedKeys)     //["1", "2", "3"]

object_2 = {
      "e3": 11,
      "e2": 12,
      "e1": 13
      }
    
let rawObjectKeys = Object.keys(object_2); 
console.log(rawObjectKeys)   //["e3", "e2", "e1"]
    
let properKeys = rawObjectKeys.map(function(element){
      return element.slice(1)
      }); 
console.log(properKeys)     //["3", "2", "1"]

答案 10 :(得分:-1)

您使用的是JS object,根据定义,它不会保留顺序。把它想象成一个键=&gt;价值图。

您应该使用array,这将保留您在插入index时插入的内容。把它想象成一个清单。

另请注意,您确实“反转了分配的顺序”,因为您每次都在同一个索引上插入元素。