简体   繁体   English

将JSON对象转换为数组以进行排序而不会丢失键/索引

[英]Converting JSON Object to Array for Sorting Without Losing Keys/Indexes

I apologize there are similar threads but I can't solve this issue. 我很抱歉有类似的话题,但我不能解决这个问题。 I have a JSON object that contains keys and values (representing file IDs and file names). 我有一个包含键和值(代表文件ID和文件名)的JSON对象。 Since a JS object cannot be sorted, I need to convert to an array, sort by value (ie, file name) NOT by key (ie, file ID). 由于无法对JS对象进行排序,因此我需要转换为数组,并按值(即文件名)而不是键(即文件ID)排序。 I can accomplish all this except when converting to array, I am losing my keys/file IDs (eg, 110, 111, 112) and they are replaced with the default array keys (0,1,2, etc.). 我可以完成所有这些操作,除了转换为数组时,我丢失了密钥/文件ID(例如110、111、112),并且将它们替换为默认的阵列密钥(0、1,2等)。

// Assign object to a var
$obj_win_top_get_files = window.top.<?php echo $_GET['files']; ?>;

Looking at the object via console.log, 通过console.log查看对象,

console.log('checked_boxes', $obj_win_top_get_files);

I see: 我懂了:

Object {110: "013_904_general.docx", 111: "013_902_info.docx", 112: "013_120_list.docx"} 对象{110:“ 013_904_general.docx”,111:“ 013_902_info.docx”,112:“ 013_120_list.docx”}

// Sort JSON object by file name ("value") rather than by id ("key")
// Create an array first since JS object is NOT sortable
arr_ids_filenames = new Array(); 

// Loop thru JS object to populate new array so it can be subsequently sorted
$.each($obj_win_top_get_files, function (key, value) {
    console.log(key, value); 
    // Populate array
    arr_ids_filenames[key] = value;
});

// Sort array by values
arr_ids_filenames.sort();
// THIS IS WHERE I AM LOSING THE FILE IDs (keys)
$.each(arr_ids_filenames, function (key, value) {
    // Array may contain keys/IDs with no values/file names so make sure there is a value
    if(value){
        console.log(key, value); 
        $the_ul.append('<li id="chk_file_' + key + '">' + value + '</li>');
    }
});

Everything works except they keys are not the file IDs (110,111,112), they are the default array keys (0,1,2). 一切正常,除了它们的键不是文件ID(110,111,112),它们是默认的数组键(0,1,2)。 It is something in the $.each() that I am not doing correctly. $ .each()中的某项我做不正确。 I am close, but have not been able to solve this one. 我很接近,但是还无法解决这一问题。 Any recommendations will be greatly appreciated. 任何建议将不胜感激。

Create an array of arrays with 2 items in the array. 创建一个数组数组,其中包含2个项目。 The key and the object. 键和对象。 Now you have an array like: 现在您有了一个类似的数组:

[
  [originalKey, obj],
  [originalKey, obj],
  [originalKey, obj]
]

then use a custom sort function: 然后使用自定义排序功能:

arr_ids_filenames.sort(function(a,b){ return a[1] - b[1] });

(NOTE: I'm assuming your objects are just integers, if not do this for sorting) (注意:我假设您的对象只是整数,如果不是为了排序,则为整数)

arr_ids_filenames.sort(function(a, b) {
  a = a[1]; // now a points to object 1
  b = b[1]; // now b points to object 2
  if (a is less than b by some ordering criterion) {
    return -1;
  }
  if (a is greater than b by the ordering criterion) {
    return 1;
  }
  // a must be equal to b
  return 0;
});

all together: 全部一起:

// Sort JSON object by file name ("value") rather than by id ("key")
// Create an array first since JS object is NOT sortable
arr_ids_filenames = new Array(); 

// Loop thru JS object to populate new array so it can be subsequently sorted
var i = 0;
$.each($obj_win_top_get_files, function (key, value) {
    console.log(key, value); 
    // Populate array
    arr_ids_filenames[i++] = [key,value];
});

// Sort array by values
arr_ids_filenames.sort(function(a,b){ return a[1] - b[1] });
// THIS IS WHERE I AM LOSING THE FILE IDs (keys)
$.each(arr_ids_filenames, function (i, v) {
    // Array may contain keys/IDs with no values/file names so make sure there is a value
    if(v[0]){
        var key = v[0];
        var value = v[1];
        $the_ul.append('<li id="chk_file_' + key + '">' + value + '</li>');
    }
});

By adding an object to an array at an index greater than the length of the array (which is what you are doing with arr_ids_filenames[key] = value ) all previous (before that index) uninitialized elements get initialized to undefined . 通过以大于数组长度的索引向数组添加对象(这是使用arr_ids_filenames[key] = value所做的事情),所有之前(在该索引之前)的未初始化元素都将初始化为undefined

For instance, doing this to an empty array: 例如,对一个空数组执行以下操作:

arr_ids_filenames[110] = 'ANYSTRING'

You get: 你得到:

arr_ids_filenames[0] = undefined;
arr_ids_filenames[1] = undefined;
// ...
arr_ids_filenames[110] = 'ANYSTRING';

Now after you sort, since: 现在进行排序之后,因为:

 'ANYSTRING' > undefined // is false
 'ANYSTRING' < undefined // is false

Your value is the smallest value and thus gets stored at index 0 with all undefined s after it. 您的值是最小值,因此将其后的所有undefined都存储在索引0 All your next storage attempts follow this pattern. 您下次的所有存储尝试都遵循此模式。

Therefore, you end up with an array of 112 elements, with your strings at the first 3 positions. 因此,最终得到一个由112个元素组成的数组,字符串位于前3个位置。 One way to solve this is to create an object: 解决此问题的一种方法是创建一个对象:

var file = {
    id: '',
    name: ''
};

And then, for each file, insert that object into a new array: 然后,对于每个文件,将该对象插入新数组:

// Loop thru JS object to populate new array so it can be subsequently sorted
$.each($obj_win_top_get_files, function (key, value) {
    console.log(key, value); 
    // Populate array
    var file = {
        id: key,
        name: value
    };
    arr_ids_filenames.push(file);
});

Sort the array by file name (by using a comparator): 按文件名对数组排序(使用比较器):

arr_ids_filenames.sort(function(a, b) { return a.name < b.name; });

And finally insert them in the DOM: 最后将它们插入DOM:

$.each(arr_ids_filenames, function(idx, file) {
  // Array may contain keys/IDs with no values/file names so make sure there is a value
  if (file.name) {
    var key = file.id;
    var value = file.name;
    $the_ul.append('<li id="chk_file_' + key + '">' + value + '</li>');
  }
});

Here's a running example: 这是一个正在运行的示例:

 var $obj_win_top_get_files = { 110: "013_904_general.docx", 111: "013_902_info.docx", 112: "013_120_list.docx" } var arr_ids_filenames = []; // Loop thru JS object to populate new array so it can be subsequently sorted $.each($obj_win_top_get_files, function(key, value) { // Populate array arr_ids_filenames.push({ id: key, name: value }); }); // Sort the array by file name (by using a comparator): arr_ids_filenames.sort(function(a, b) { return a.name < b.name; }); console.log('sort: ' + JSON.stringify(arr_ids_filenames)); // And finally insert them in the DOM: var $the_ul = $('ul'); $.each(arr_ids_filenames, function(idx, file) { if (file.name) { var key = file.id; var value = file.name; console.log('here'); $the_ul.append('<li id="chk_file_' + key + '">' + value + '</li>'); } }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <ul></ul> 

UPDATED SOLUTION: 更新的解决方案:

The original solution I provided does not work in IE11. 我提供的原始解决方案在IE11中不起作用。 Console was returning a "SCRIPT1003" error which, upon further research, led me to this SO question: JavaScript in IE11 giving me script error 1003 控制台返回“ SCRIPT1003”错误,经进一步研究后,我提出了以下问题: IE11中的JavaScript给我脚本错误1003

IE11 doesn't support ES6 key-pair shorthand. IE11不支持ES6密钥对速记。 Taking this into account, the updated code should look like this: 考虑到这一点,更新后的代码应如下所示:

var arr_ids_filenames  = [];

// convert your file list into an array of objects
$.each($obj_win_top_get_files, function(key, name) {
    // use key:pair format
    arr_ids_filenames.push({
        key: key, 
        name: name
    });
});

// sort by file name (and not by key/id)
arr_ids_filenames.sort(function(a, b) {
    return ((a.name < b.name) ? -1 : ((a.name > b.name) ? 1 : 0));
});

// add items to list   
$.each(arr_ids_filenames, function(index, file) {
    $the_ul.append('<li id="chk_file_' + file.key + '">' + file.name + '</li>')
});

See the code in action: https://jsfiddle.net/7y7qps88/53/ 参见运行中的代码: https : //jsfiddle.net/7y7qps88/53/

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

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