2016-06-01 2 views
-1

Айв получил массив объектов, что-то вроде этого:объекты JavaScript сортировочные

tab = [ 
{ top: true, i: 2, bottom: false }, 
{ top: true, i: 5, bottom: false }, 
{ top: true, i: 6, bottom: false }, 
{ top: false, i: 1, bottom: false }, 
{ top: false, i: 8, bottom: false }, 
{ top: false, i: 1, bottom: false }, 
{ top: false, i: 2, bottom: true }, 
{ top: false, i: 3, bottom: true }, 
{ top: false, i: 1, bottom: true }, 
{ top: true, i: 5, bottom: false } 
] 

И я хочу, чтобы отсортировать его, позволяет сказать, что мы имеем объект А и Б:

  1. если сверху == правда, поместить его в верхней части списка
  2. , если Ai == Bi, положить A и B рядом друг с другом независимо от того, что
  3. если снизу == верно, поместите его в конец списка

Так массив сверху, отсортированные будет выглядеть примерно так:

{ top: true, i: 2, bottom: false }, 
{ top: false, i: 2, bottom: true }, 
{ top: true, i: 5, bottom: false }, 
{ top: true, i: 5, bottom: false }, 
{ top: true, i: 6, bottom: false }, 
{ top: false, i: 8, bottom: false }, 
{ top: false, i: 1, bottom: false }, 
{ top: false, i: 1, bottom: false }, 
{ top: false, i: 1, bottom: true }, 
{ top: false, i: 3, bottom: true } 

Im используя Array.sort, но я не могу заставить его работать, и это сводит меня с ума, любую идею?

EDIT: Я вижу, что правила Арент достаточно ясно, так Больная попытка быть более указать в настоящее время:

  1. если Ai == Bi, положить А и Б рядом друг с другом, независимо от того, что
  2. если верх == верно, поместите его в верхней части списка
  3. если снизу == верно, поместите его в конец списка

  4. A.top: правда, a.Bottom: правда - невозможно случай

  5. A.top: true, B.top: true, Ai! = Bi-order не имеет значения, то же самое с нижним
  6. top имеет более высокий приоритет, чем прижим, так что если A.top: true, B.bottom: true, Ai = Bi, то положим их на верхние
+3

Было бы хорошо, чтобы опубликовать пример кода, который произвел пример некорректного выхода. –

+2

'если A.i == B.i, положите A и B рядом друг с другом, независимо от того, что' - не должно ли это быть правилом 1? –

+1

И как вы сортируете два элемента как с 'top' true, так и с разными' i'? Или у вас есть предмет с 'top' true и' bottom' true? Ваш вид, похоже, не полностью определен. –

ответ

1

Это предложение с одной сортировкой и объектом для порядка сортировки. Он использует значение как значение по умолчанию 1e6, достаточно большое, чтобы быть больше значения i. Если он не назначен, он использует половинное значение.

var tab = [{ top: true, i: 2, bottom: false }, { top: true, i: 5, bottom: false }, { top: true, i: 6, bottom: false }, { top: false, i: 1, bottom: false }, { top: false, i: 8, bottom: false }, { top: false, i: 1, bottom: false }, { top: false, i: 2, bottom: true }, { top: false, i: 3, bottom: true }, { top: false, i: 1, bottom: true }, { top: true, i: 5, bottom: false }], 
 
    object = { top: {}, bottom: {} }; 
 

 
tab.forEach(function (t) { 
 
    object.top[t.i] = object.top[t.i] || 0.5e6; 
 
    object.bottom[t.i] = object.bottom[t.i] || 0.5e6; 
 
    if (t.top) { 
 
     object.top[t.i] = t.i; 
 
    } 
 
    if (t.bottom) { 
 
     object.bottom[t.i] = 1e6 + t.i; 
 
    } 
 
}); 
 

 
tab.sort(function (a, b) { 
 
    return object.top[a.i] - object.top[b.i] || object.bottom[a.i] - object.bottom[b.i]; 
 
}); 
 
console.log(tab);

+0

Мне нравится решение, и я пытаюсь адаптировать его к моему сценарию. Можете ли вы посмотреть на это: http://jsbin.com/bariminawu/edit?html,js,console,output? Единственная проблема с 777-444-111, она нарушает правило номер 6 – Pawel

+1

@Pawel, я предлагаю попробовать с большим значением, большим, чем вдвое больше максимального значения, у вас есть. введите значение как 1e10 или для половины 0.5e10 или 5e9. [jsbin] (http://jsbin.com/venogakoju/1/edit?html,js,console,output) –

+1

Спасибо, работает как шарм. – Pawel

1

Вы можете использовать встроенный метод сортировки JavaScript для массивов. Он принимает обратный вызов, который может использоваться для сравнения элементов для определения порядка сортировки. Обратный вызов вызывается с парами элементов из массива. Если первый аргумент, предоставленный обратному вызову, должен появиться первым, верните отрицательное число, если оно не имеет значения return 0, а если второе должно появиться, сначала верните положительное число. В вашем случае, вызов будет выглядеть примерно так:

var tab = [ 
 
    { top: true, i: 2, bottom: false }, 
 
    { top: true, i: 5, bottom: false }, 
 
    { top: true, i: 6, bottom: false }, 
 
    { top: false, i: 1, bottom: false }, 
 
    { top: false, i: 8, bottom: false }, 
 
    { top: false, i: 1, bottom: false }, 
 
    { top: false, i: 2, bottom: true }, 
 
    { top: false, i: 3, bottom: true }, 
 
    { top: false, i: 1, bottom: true }, 
 
    { top: true, i: 5, bottom: false } 
 
]; 
 

 
var hasTop = {}; 
 
var hasBottom = {}; 
 

 
tab.forEach(function (t) { 
 
    if (t.top) { 
 
     hasTop[t.i] = true; 
 
    } 
 
    
 
    if (t.bottom) { 
 
     hasBottom[t.i] = true; 
 
    } 
 
}); 
 

 
tab.sort(function (a, b) { 
 
    if (hasTop[a.i] && hasTop[b.i]) { 
 
     return a.i - b.i; 
 
    } else if (hasTop[a.i] && !hasTop[b.i]) { 
 
     return -1; 
 
    } else if (!hasTop[a.i] && hasTop[b.i]) { 
 
     return 1; 
 
    } else if (hasBottom[a.i] && hasBottom[b.i]) { 
 
     return a.i - b.i; 
 
    } else if (hasBottom[a.i] && !hasBottom[b.i]) { 
 
     return 1; 
 
    } else if (!hasBottom[a.i] && hasBottom[b.i]) { 
 
     return -1; 
 
    } else { 
 
     return 0; 
 
    } 
 
}); 
 

 
document.getElementById("foo").innerText = JSON.stringify(tab, null, 4);
#foo { 
 
    white-space: pre; 
 
}
<div id="foo"> 
 
</div>

Кроме того, имейте в виду, что сортировка встроенный сортирует массив на месте вместо того, чтобы создать новый отсортированный массив.

EDIT:

В первоначальном ответе, я неправильно понял описание правил, но после обновления и более тщательного рассмотрения я понял, проблема. Порядок сортировки зависит не только от локальных свойств этих двух элементов, но имеет ли какой-либо элемент с тем же индексом (i) свойство top или bottom, которое является истинным глобальным свойством массива. Чтобы справиться с этим, вы должны сделать проход через данные и записать, если есть какой-либо элемент с атрибутом top или bottom, который является истинным с данным индексом. Может быть умный способ сделать это, находясь внутри обратного вызова сортировки, но я его не видел. Кроме того, обратите внимание, что мой оригинальный пост получил неправильное значение возвращаемого значения обратного вызова сортировки.Это исправлено в этом редактировании.

+1

[Не забудьте« вернуть 0'] (http: // stackoverflow. com/q/20883421/1048572) в конце – Bergi

+0

Btw, вы можете упростить это, чтобы возвращать ai-bi || a.top - b.top || b.bottom - a.bottom; ' – Bergi

+0

Я отредактирую его, чтобы включить« return 0 »в конец, хороший улов, но я думаю, что« упрощение », хотя и более кратким, может смущать людей, не знакомых с Короткое замыкание и тираж кода JavaScript. –

Смежные вопросы