简体   繁体   English

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

[英]How to prevent automatic sort of Object numeric property?

Why I met this problem: I tried to solve an algorithm problem and I need to return the number which appeared most of the times in an array.为什么我会遇到这个问题:我试图解决一个算法问题,我需要返回数组中大部分时间出现的数字。 Like [5,4,3,2,1,1] should return 1. And also when two number appear same time as the maximum appearance return the one came first.像 [5,4,3,2,1,1] 应该返回 1。而且当两个数字与最大出现时间同时出现时,返回第一个。 Like [5,5,2,2,1] return 5 because 5 appear first.像 [5,5,2,2,1] 返回5因为5首先出现。 I use an object to store the appearance of each number.我使用一个对象来存储每个数字的外观。 The key is the number itself.关键是数字本身。

So When the input is [5,5,2,2,1] my object should be Object {5: 2, 2: 2, 1: 1} but actually I got Object {1: 1, 2: 2, 5: 2} So When I use for..in to iterate the object I got 2 returned instead of 5 .所以当输入是 [5,5,2,2,1] 我的对象应该是Object {5: 2, 2: 2, 1: 1}但实际上我得到了Object {1: 1, 2: 2, 5: 2}所以当我使用 for..in 迭代对象时,我得到了2而不是5 So that's why I asked this question.所以这就是我问这个问题的原因。

This problem occurs in Chrome console and I'm not sure if this is a common issue: When I run the following code这个问题出现在 Chrome 控制台中,我不确定这是否是一个常见问题:当我运行以下代码时

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

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

But when I reverse the order of assignment like:但是当我颠倒分配顺序时:

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

a is also: Object {0: 1, 1: 2, 2: 3} The numeric property automatic sorted in ascending order. a也是: Object {0: 1, 1: 2, 2: 3}数值属性自动升序排序。 I tried prefix or postfix the numeric property like我试过前缀或后缀数字属性,如

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

And this keep the property order.这保持了财产秩序。 Is this the best way to solve the problem?这是解决问题的最佳方法吗? And is there anyway to prevent this auto sort behavior?无论如何要防止这种自动排序行为? Is this only happen in Chrome V8 JavaScript engine?这只发生在 Chrome V8 JavaScript 引擎中吗? Thank you in advance!先感谢您!

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

This can prevent automatic sort of Object numeric property.这可以防止对象数字属性的自动排序。

You really can't rely on order of an object fields in JavaScript, but I can suggest to use Map ( ES6/ES2015 standard ) if you need to preserve order of your key, value pair object.您确实不能依赖 JavaScript 中对象字段的顺序,但是如果您需要保留key, value对对象的顺序,我可以建议使用MapES6/ES2015 标准)。 See the snippet below:请参阅下面的片段:

 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

This is an old topic but it is still worth mentioning as it is hard to find a straight explanation in one-minute googling.这是一个古老的话题,但仍然值得一提,因为在一分钟的谷歌搜索中很难找到直接的解释。

I recently had a coding exercise that finding the first occurrence of the least/most frequent integer in an array, it is pretty much the same as your case.我最近进行了一个编码练习,在数组中找到第一个出现的最少/最频繁的整数,它与您的情况几乎相同。

I encountered the same problem as you, having the numeric keys sorted by ASC in JavaScript object, which is not preserving the original order of elements, which is the default behavior in js.我遇到了和你一样的问题,在 JavaScript 对象中数字键按 ASC 排序,这不保留元素的原始顺序,这是 js 中的默认行为。

A better way to solve this in ES6 is to use a new data type called: Map在 ES6 中解决这个问题的更好方法是使用一种新的数据类型: Map

Map can preserve the original order of elements(pairs), and also have the unique key benefit from object. 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"

However, using the object data type can also solve the problem, but we need the help of the input array to get back the original order of elements:不过,使用对象数据类型也可以解决问题,但是我们需要借助输入数组来找回元素的原始顺序:

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 

You are using a JS object , that by definition does not keep order.您正在使用 JS object ,根据定义,该object不保持顺序。 Think of it as a key => value map.将其视为键 => 值映射。

You should be using an array , that will keep whatever you insert on the index you inserted it into.您应该使用一个array ,它将保留您在插入它的index插入的任何内容。 Think of it as a list.把它想象成一个列表。

Also notice that you did not in fact "reverse the order of the assignment", because you inserted elements on the same index every time.还要注意,您实际上并没有“颠倒分配的顺序”,因为您每次都在同一索引上插入元素。

I've stumbled with this issue with our normalised array which keyed with Ids> After did my research, I found out there's no way to fix using the object keys because by default the Javascript is sorting any object key with number when you iterate it.我在使用 Ids> 键控的规范化数组时偶然发现了这个问题。经过我的研究,我发现无法使用对象键进行修复,因为默认情况下,Javascript 会在您迭代时使用数字对任何对象键进行排序。

The solution I've done and it worked for me is to put a 'sortIndex' field and used that to sort the list.我已经完成并且对我有用的解决方案是放置一个“sortIndex”字段并用它来对列表进行排序。

instead of generating an object like {5: 2, 2: 2, 1: 1}而不是生成像{5: 2, 2: 2, 1: 1}

generate an array to the effect of生成一个数组的效果

[
   {key: 5, val: 2},
   {key: 2, val: 2},
   {key: 1, val: 1}
]

or... keep track of the sort order in a separate value or key或者...在单独的值或键中跟踪排序顺序

The simplest and the best way to preserve the order of the keys in the array obtained by Object.keys() is to manipulate the Object keys a little bit.保留Object.keys()获得的数组中键的顺序的最简单和最好的方法是稍微操作 Object 键。

insert a "_" in front of every key name.在每个键名前插入“_”。 then run the following code!然后运行下面的代码!

 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"]

You get the desired order in the array with just a few lines of code.只需几行代码,您就可以在数组中获得所需的顺序。 hApPy CoDiNg :)快乐编码 :)

To prevent the automatic sort of numeric keys of Object in Javascript, the best way is to tweak the Object keys a little bit.为了防止 JavaScript 中对象的数字键自动排序,最好的方法是稍微调整对象键。

We can insert an "e" in front of every key name to avoid lexicographical sorting of keys and to get the proper output slice the "e", by using the following code;我们可以在每个键名前插入一个“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"]

I came across this same problem, and after search a lot about that, i found out that the solution to prevent this behavior is make key as string.我遇到了同样的问题,经过大量搜索后,我发现防止这种行为的解决方案是将密钥设为字符串。

Like that:像那样:

{"a": 2, "b": 2}
  1. you can use Map() in javascript ES6 which will keep the order of the keys insertion.您可以在 javascript ES6 中使用 Map() ,它会保持键插入的顺序。

  2. just trying to solve your problem in an alternative solution, recently like to practise leetcode-like question只是想用另一种解决方案解决你的问题,最近喜欢练习类似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);
}

simply do that while you're working with a numeric array index只需在使用数字数组索引时执行此操作

data      = {}
data[key] = value

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM