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

时间:2015-11-18 22:33:48

标签: javascript arrays json sorting object

我道歉有类似的线程,但我无法解决这个问题。我有一个JSON对象,包含键和值(表示文件ID和文件名)。由于JS对象无法排序,我需要转换为数组,按值(即文件名)排序,不按键(即文件ID)。我可以完成所有这些,除非转换为数组,我丢失了我的键/文件ID(例如,110,111,112),它们被默认的数组键(0,1,2等)替换。

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

通过console.log查看对象,

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

我明白了:

对象{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>');
    }
});

一切正常,除了它们的键不是文件ID(110,111,112),它们是默认的数组键(0,1,2)。 $ .each()中的内容我没有正确完成。我很接近,但未能解决这个问题。任何建议都将不胜感激。

3 个答案:

答案 0 :(得分:2)

创建一个包含数组中2个项目的数组数组。关键和对象。现在你有一个像:

这样的数组
[
  [originalKey, obj],
  [originalKey, obj],
  [originalKey, obj]
]

然后使用自定义排序功能:

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

(注意:我假设你的对象只是整数,如果不是这样做的话来排序)

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;
});

所有在一起:

// 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>');
    }
});

答案 1 :(得分:0)

通过向数组添加一个索引更大的数组,而不是数组的长度(这是您使用arr_ids_filenames[key] = value执行的操作)所有先前(在该索引之前)未初始化的元素初始化为undefined

例如,对空数组执行此操作:

arr_ids_filenames[110] = 'ANYSTRING'

你得到:

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

排序之后,现在:

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

您的值是最小值,因此将其存储在索引0之后,其后面包含所有undefined个。您的所有下一次存储尝试都遵循此模式。

因此,您最终会得到一个包含112个元素的数组,其中您的字符串位于前3个位置。解决此问题的一种方法是创建一个对象:

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

然后,对于每个文件,将该对象插入新数组中:

// 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);
});

按文件名对数组进行排序(使用比较器):

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

最后将它们插入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>');
  }
});

这是一个正在运行的例子:

&#13;
&#13;
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>');
  }
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul></ul>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

更新的解决方案:

我提供的原始解决方案在IE11中不起作用。控制台返回“SCRIPT1003”错误,经过进一步研究,我引发了这个问题:JavaScript in IE11 giving me script error 1003

IE11不支持ES6密钥对速记。考虑到这一点,更新的代码应如下所示:

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>')
});

请参阅操作代码:https://jsfiddle.net/7y7qps88/53/