Подтвердить что ты не робот

Как отсортировать объект Javascript или преобразовать его в массив?

У меня есть данные JSON, которые я получаю с сервера. В моем JavaScript я хочу сделать некоторую сортировку. Я думаю, что функция sort() будет делать то, что я хочу.

Однако, похоже, что JavaScript преобразует данные JSON в объект сразу по прибытии. Если я попытаюсь использовать метод sort(), я получаю ошибки a-много (используя Firebug для тестирования).

Я просмотрел сеть, и все, кажется, говорят, что, с одной стороны, объекты JSON уже являются массивами JavaScript, а также что объекты можно обрабатывать так же, как массивы. Как и на этот вопрос, где в одном из ответов парень говорит: "Объект объекта - это ваши данные - вы можете получить к нему доступ, как и массив."

Однако это не совсем так. JavaScript не позволит мне использовать sort() для моего объекта. И поскольку предположение по умолчанию состоит в том, что все они одно и то же, нет никаких инструкций о том, как преобразовать объект в массив, или заставить JavaScript обрабатывать его как один или что-то в этом роде.

Итак... как мне получить JavaScript, чтобы позволить мне рассматривать эти данные как массив и сортировать() это?

Выход журнала консоли моего объекта выглядит следующим образом (я хочу, чтобы сортировать по значениям на уровне ")":

ОБЪЕКТ JSONdata​​p >

{ 
1: {
    displayName: "Dude1",
    email: "[email protected]<mailto:[email protected]>",
    lastActive: 1296980700, 
    level: 57, 
    timeout: 12969932837
}, 2: {
    displayName: "Dude2",
    email: "[email protected]<mailto:[email protected]>",
    lastActive: 1296983456,
    level: 28,
    timeout: 12969937382
}, 3: {
    displayName: "Dude3",
    email: "[email protected]<mailto:[email protected]>",
    lastActive: 1296980749,
    level: 99,
    timeout: 129699323459
} 
}
4b9b3361

Ответ 1

Array.prototype.slice.call(arrayLikeObject)

- стандартный способ преобразования и массивный объект в массив.

Это действительно работает только для объекта arguments. Преобразование общего объекта в массив - это немного боль. Здесь источник из underscore.js:

_.toArray = function(iterable) {
    if (!iterable)                return [];
    if (iterable.toArray)         return iterable.toArray();
    if (_.isArray(iterable))      return iterable;
    if (_.isArguments(iterable))  return slice.call(iterable);
    return _.values(iterable);
};

_.values = function(obj) {
    return _.map(obj, _.identity);
};

Оказывается, вам нужно будет зациклиться на вашем объекте и сопоставить его с массивом самостоятельно.

var newArray = []
for (var key in object) {
    newArray.push(key);
}

Вы смешиваете понятия массивов и "ассоциативных массивов". В JavaScript объекты типа действуют как ассоциативный массив, так как вы можете получить доступ к данным в формате object["key"]. Они не являются реальными ассоциативными массивами, поскольку объекты являются неупорядоченными списками.

Объекты и массивы сильно различаются.

Пример использования подчеркивания:

var sortedObject = _.sortBy(object, function(val, key, object) {
    // return an number to index it by. then it is sorted from smallest to largest number
    return val;
});

Смотрите живой пример

Ответ 2

Вы должны иметь возможность конвертировать объект JavaScript в массив, подобный этому...

var obj = {
    '1': 'a',
    '2': 'b',
    '3': 'c'  
};

var arr = [];

for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      arr.push(obj[key]);  
    }
}

console.log(arr); // ["a", "b", "c"]

Посмотрите на jsFiddle.

Ответ 3

Если ваш объект JavaScript является подобным массиву объекту, то есть экземпляр объекта с допустимым численным свойством length, то вы можете напрямую использовать на нем много методов массива, благодаря call. Например:

// Sorts the given objet in-place as if it was an array
Array.prototype.sort.call(yourObject);

Итак, если вы знаете количество записей для сортировки (Как эффективно подсчитывать количество ключей/свойств объекта в JavaScript?), вы можете сделать

yourObject.length = theNumberOfEntries;
Array.prototype.sort.call(yourObject);
// Optionally: delete yourObject.length;

Обратите внимание, что это будет только сортировка свойств, индексированных значениями "0", "1", "2",... до length - 1 включительно, как в массиве. Объект других свойств не будет переназначен.

Ответ 4

Большинство из этих ответов слишком усложняют проблему или используют JQuery или Underscore, тогда как OP никогда не запрашивал их.

Вы можете преобразовать объект в массив следующим образом:

myArray= Object.keys(data).map(function(key) { return data[key] });

И отсортируйте результат следующим образом:

myArray.sort(function(x, y) {return x.level - y.level});

Если вам нужен id/index, вам нужно сделать немного больше:

Object.keys(data).map(function(key) { 
  var obj = data[key];
  obj.index = key;
  return obj 
});

Ответ 5

Я недавно наткнулся на эту проблему, пытаясь сгруппировать массив объектов одним из его свойств, в результате чего один объект я не мог сортировать.

Конкретно это массив сообщений в блогах, которые я хотел объединить в год, и отсортировать их по годам. Я использовал утилиту underscore:

var grouped = _.groupBy(blogposts, function(post){
  var date = new Date(post.publication_date)
  return date.getFullYear()
})
//=> { 2010: [blogpost, blogpost,etc], 2011: [blogpost, etc] }

Как пояснил @Raynos, мне пришлось сначала обработать какой-то массив, прежде чем сортировать его...

Получается, что подчеркивание (1.4) имеет небольшую полезную утилиту под названием pairs, которая отобразит значение {key: value} вашего объекта в массиве [ключ, значение]. Эквивалент:

var paired = _.map(grouped, function(val, key){
  return [key, val]
})
//=> [ [2010, [blogpost, blogpost, ...] ], [2011, [blogpost, blogpost, ...]]...]

Оттуда вы можете легко отсортировать первый член каждой пары.

Здесь конечный результат:

var grouped = _.groupBy(result.resource, function(resource){
  var date = new Date(resource.pub_date)
  return date.getFullYear() //+ "." + (date.getMonth()+1)
})

var paired = _.pairs(grouped)

var sorted = _.sortBy(paired, function(pairs){
  return -parseInt(pairs[0])
})

return sorted;
// Giving me the expected result:
//=> [ [2013, [blogpost, blogpost, ...] ], [2012, [blogpost, blogpost, ...]]...]

Я уверен, что есть лучший и более эффективный способ, но, исходя из Ruby, этот код мне сразу понятен.

Ответ 6

jQuery предлагает функцию отображения, которая будет перебирать каждый элемент в массиве или объекте и отображать результаты в новый массив.

До того, как только jQuery 1.6 поддерживает только массивы перемещения только $.map().

Мы можем использовать это для преобразования любого объекта в массив следующим образом:

  myArray = $.map(myObject, function (el) {
    return el;
  });

Но... если функция обратного вызова возвращает null или undefined, то это значение удалено из массива, в большинстве случаев это полезно, но это может вызвать проблемы, если вам нужно null значения в myArray.

jQuery предлагает решение для этого... вернуть значение в виде массива с единственным значением

myArrayWithNulls = jQuery.map(myObject, function (el) {
  return [el];
});

Вот сценарий, демонстрирующий два подхода: http://jsfiddle.net/chim/nFyPE/

http://jsperf.com/object-to-array-jquery-2

Ответ 7

Я написал небольшую функцию для рекурсивного преобразования объекта со свойствами, которые также могут быть объектами для многомерного массива. Этот код зависит от подчеркивания или lodash для методов forEach и toArray.

function deepToArray(obj) {
    var copy = [];


    var i = 0;
    if (obj.constructor == Object ||
        obj.constructor == Array) {

        _.forEach(obj, process);

    } else {

        copy = obj;

    }


    function process(current, index, collection) {

        var processed = null;
        if (current.constructor != Object &&
            current.constructor != Array) {
            processed = current;
        } else {
            processed = deepToArray(_.toArray(current));
        }

        copy.push(processed);

    }

    return copy;
}

Вот скрипка: http://jsfiddle.net/gGT2D/

Примечание. Это было записано для преобразования объекта, который изначально был массивом обратно в массив, поэтому любые значения ключа индекса без массива будут потеряны.