#javascript #sorting #ionic-framework
#javascript #сортировка #ionic-framework
Вопрос:
У меня есть массив объектов:
- A: ПОЛУЧЕНИЕ A С РАССТОЯНИЯ 9,96
- B: ОТСЕВ A С РАССТОЯНИЕМ 13,46
- C: ПОЛУЧЕНИЕ B С РАССТОЯНИЕМ 4.46
- D: ВЫПАДАЮЩИЙ список B С РАССТОЯНИЕМ 1,06
- E: ПОЛУЧЕНИЕ C С РАССТОЯНИЯ 3,86
- F: ОТСЕВ C С РАССТОЯНИЕМ 17,86
[]
0:{
name: "A"
distance: "9.96"
key4: "zzz"
log: "2"
type: "Pickup"
}
1:{
name: "B"
distance: "13.46"
key4: "zzz"
key5: "true"
log: "1"
type: "Dropoff"
}
2:{
name: "C"
distance: "1.06"
key4: "ggg"
log: "2"
type: "Dropoff"
}
3:{
name: "D"
distance: "4.46"
key4: "ggg"
key5: "true"
log: "1"
type: "Pickup"
}
4:{
name: "E"
distance: "3.86"
key4: "jjj"
log: "2"
type: "Pickup"
}
5:{
name: "F"
distance: "17.86"
key4: "jjj"
key5: "true"
log: "1"
type: "Dropoff"
}
ETA:
Мой ожидаемый результат:
- A: ПОЛУЧЕНИЕ C С РАССТОЯНИЕМ 3,86
- B: ПОЛУЧЕНИЕ B С РАССТОЯНИЕМ 4.46
- C: ВЫПАДАЮЩИЙ список B С РАССТОЯНИЕМ 1,06
- D: ПОЛУЧЕНИЕ A С РАССТОЯНИЕМ 9,96
- E: УДАЛЕНИЕ A С РАССТОЯНИЕМ 13,46
- F: ОТСЕВ C С РАССТОЯНИЕМ 17,86
Я тщетно пытался сначала отсортировать по расстоянию, но все еще получаю, где «key4» одного объекта равен «key4» другого объекта, а затем, если «log» первого объекта больше второго «log», то тот, у которого «log 2», размещается выше. Не имеет значения, где размещен второй объект, главное, чтобы он был ниже первого объекта, при этом все объекты сортируются с учетом расстояния. Я бы хотел в конечном итоге использовать CEDABF. Я хотел бы, чтобы для совпадающей пары объектов получение всегда происходило перед удалением, независимо от разницы в расстоянии, но получение не обязательно должно происходить непосредственно перед этим удалением. Порядок может быть Pickup1, Dropoff1, Pickup2, Pickup3, Dropoff3, Dropoff2, и это зависит от расстояния. Здесь Dropoff2 находится после Pickup2, но не сразу после него. До сих пор мне удавалось сортировать по возрастанию расстояния, но тогда критерии игнорируются, и аналогично, если я сортирую по key4 и регистрирую, то расстояние игнорируется. Буду признателен за любую помощь.
Это то, что я пробовал:
let sortA = this.array.map((data, idx) => {
return {idx: idx, data: data}
})
sortA.sort((a,b) => {
if (a.data.key4 == b.data.key4) {
if (a.idx > b.idx)
return -1;
if (a.idx < b.idx)
return 1;
}
return a.data.distance - b.data.distance
})
this.newarray = sortA.map((val) => {
return val.data
})
And this gives:
- A: DROPOFF B WITH DISTANCE 1.06
- B: PICKUP C WITH DISTANCE 3.86
- C: PICKUP B WITH DISTANCE 4.46
- D: PICKUP A WITH DISTANCE 9.96
- E: DROPOFF A WITH DISTANCE 13.46
-
F: DROPOFF C WITH DISTANCE 17.86
0:{
name: «C»
distance: «1.06»
key4: «ggg»
log: «2»
type: «Dropoff»
}1:{
name: «E»
distance: «3.86»
key4: «jjj»
log: «2»
type: «Pickup»
}2:{
name: «D»
distance: «4.46»
key4: «ggg»
key5: «true»
log: «1»
type: «Pickup»
}3:{
name: «A»
distance: «9.96»
key4: «zzz»
log: «2»
type: «Pickup»
}4:{
name: «B»
distance: «13.46»
key4: «zzz»
key5: «true»
log: «1»
type: «Dropoff»
}5:{
name: «F»
distance: «17.86»
key4: «jjj»
key5: «true»
log: «1»
type: «Dropoff»
}
This only sorts distances but ignores «key4» and «idx» such that Dropoff(DROPOFF B) with key4=»ggg» is before it’s corresponding Pickup.
I also tried:
this.array.sort(fieldSorter(['distance', '-key4']));
fieldSorter(fields) {
return (a, b) => {
return fields
.map((o) => {
let dir = 1;
if (o[0] === '-') {
dir = -1;
o=o.substring(1);
console.log(o[0], 'ooo')
}
if (a[o] > b[o]) return dir;
if (a[o] < b[o]) return -(dir);
return 0;
})
.reduce((p,n) => {
return p ? p : n;
}, 0);
};
}
This gives me the same result as above:
- A: DROPOFF B WITH DISTANCE 1.06
- B: PICKUP C WITH DISTANCE 3.86
- C: ПОЛУЧЕНИЕ B С РАССТОЯНИЕМ 4.46
- D: ПОЛУЧЕНИЕ A С РАССТОЯНИЕМ 9,96
- E: УДАЛЕНИЕ A С РАССТОЯНИЕМ 13,46
-
F: ОТСЕВ C С РАССТОЯНИЕМ 17,86
0: { имя: «C» расстояние: «1.06» ключ4: «ggg» журнал: «2» тип: «Выпадающий» }
1:{ имя: «E» расстояние: «3.86» ключ4: «jjj» журнал: «2» тип: «Пикап» }
2:{ имя: «D» расстояние: «4.46» ключ4: «ggg» ключ5: «true» журнал: «1» тип: «Пикап» }
3:{ имя: «A» расстояние: «9.96» ключ4: «zzz» журнал: «2» тип: «Пикап» }
4:{ имя: «B» расстояние: «13.46» ключ4: «zzz» ключ5: «true» журнал: «1» тип: «Выпадающий» }
5:{ имя: «F» расстояние: «17.86» ключ4: «jjj» ключ5: «true» журнал: «1» тип: «Выпадающий» }
Это сортирует «key4» только в том случае, если два расстояния равны.
Наконец, я попробовал, добавил ли я атрибут «buyerId» к каждому удаленному объекту. :
var stored = {}, newTab = [];
for(var i = 0, iLimit = array.length; i < iLimit; i ) {
if(array[i].buyerId) {
stored[i] = array[i];
} else {
newTab.push(array[i]);
}
}
newTab.sort((a,b) => {
var aVal = parseInt(a.distance);
var bVal = parseInt(b.distance);
if (aVal===bVal) {
return 0;
} else {
return aVal < bVal ? -1 : 1;
}
});
for(var indice in stored) {
newTab.splice(1, 0, stored[indice]);
}
Число после сращивания предназначено только для того, чтобы показать, как будут вставляться выпадающие списки. Выборки сортируются по расстоянию до тех пор, пока не будет выполнена вставка, а затем сортировка продолжается после этого.
Это дает мне:
- A: ПОЛУЧЕНИЕ C С РАССТОЯНИЕМ 3,86
- B: ПОЛУЧЕНИЕ B С РАССТОЯНИЕМ 4.46
- C: ВЫПАДАЮЩИЙ список B С РАССТОЯНИЕМ 1,06
- D: УДАЛЕНИЕ A С РАССТОЯНИЕМ 13,46
- E: ОТСЕВ C С РАССТОЯНИЕМ 17,86
- E: ПОЛУЧЕНИЕ A С РАССТОЯНИЯ 9,96
Комментарии:
1. Ваш пример просто отсортирован по расстоянию. Вы говорите, что также намерены применять это правило в отношении key4 и log, но что неясно — и не показано в вашем примере — это то, что бы вы сделали, если бы запись с log = 2 также имела большее расстояние. Как только вы это проясните, может оказаться возможным определить порядок сортировки, а может и нет — потому что существуют правила, которым порядок сортировки должен следовать с точки зрения согласованности при сравнении разных элементов, и эти ограничения могут не работать в рамках этих правил — в этом случае вам придется выполнить некоторое пользовательское переупорядочение, а не полностью полагаться на метод сортировки.
2. Спасибо за ваш комментарий. Если log= 2 определенного объекта имеет большее расстояние, чем соответствующий ему объект log = 1 (где key4 = key4) , то этот объект log 2 по-прежнему размещается перед соответствующим объектом log 1.
3. Как я уже сказал, это несколько неясно, и я думаю, что для вопроса нужен пример, который показывает ожидаемый результат в этой ситуации.
4. я хочу, чтобы для каждого пикапа, который приходит первым, даже если Dropoff ближе, и если есть один Пикап1 (например, расстояние = 5) и другой Пикап2 (например, расстояние = 7), в то время как Dropoff1 (например, расстояние = 13) и Dropoff2 (например, расстояние = 9), то порядок был бы Pickup1, Pickup2, Dropoff2, Dropoff1
5. Я отредактировал свой вопрос, чтобы, надеюсь, прояснить больше. Каждый объект типа = Получение имеет соответствующий объект типа = удаление. Они сопоставляются на основе равного ключа4.
Ответ №1:
ОБНОВЛЕНИЕ — Я обнаружил некоторую «серую зону» вокруг ограничений sort
метода, которые я привожу, и которые я разъясняю…
Добро пожаловать в Stack Overflow.
Основываясь на обсуждении в комментариях, у меня есть более четкое представление о том, что вы пытаетесь. Тем не менее, ключевым элементом качественного вопроса является то, что в нем есть пример, который показывает ожидаемое поведение (и показывает, как это поведение отличается от результатов от использованных методов). В настоящее время я вижу единственный пример, который не демонстрирует никакой разницы в результатах от «сортировки по расстоянию». Хотя вы отдельно описываете, почему «сортировать по расстоянию» — это не то, что вы хотите, должен присутствовать пример, демонстрирующий это различие.
Поскольку такого примера нет (даже после того, как он был запрошен), я предоставлю ad большую часть ответа, насколько смогу, с предоставленной информацией, но это сопровождается напоминанием о том, что на SO качество ответов будет зависеть от качества вопроса.
Итак, что я могу определенно сказать, так это то, что вы сталкиваетесь с ограничениями того, что может сделать стандартный sort
метод.
Когда вы предоставляете функцию упорядочивания sort
, она должна иметь возможность просматривать любые два элемента и говорить: «этот должен идти перед тем», без необходимости контекста (например, может ли существовать третий элемент, соответствующий определенным критериям). (При некоторых обстоятельствах существует небольшое пространство для обхода этого ограничения, о котором я расскажу через минуту.)
Так, например, если у вас было
- A: ПОЛУЧЕНИЕ A С РАССТОЯНИЯ 5
- B: УДАЛЕНИЕ A С РАССТОЯНИЕМ 1
- C: ПОЛУЧЕНИЕ B С РАССТОЯНИЯ 3
функция сравнения, предоставляемая sort
, должна иметь возможность просматривать B
и C
и, без каких-либо знаний о том, что A
существует или нет, решать, B
идет ли это впереди C
в списке. Аналогично, он должен иметь возможность сравнивать A
и C
без каких-либо знаний о B
. И результаты должны быть согласованными, такими, что если в нем указано x>y
и y>z
, то в нем также должно быть указано x>z
.
Глядя на A
и C
отдельно, казалось бы, это C
должно быть на первом месте.
Глядя на B
и C
отдельно, казалось бы, это B
должно быть на первом месте.
Глядя на A
и B
, мы знаем, что A
это должно быть первым.
A > C > B > A
Таким образом, не может быть согласованного правила упорядочения, к которому может применяться sort
алгоритм.
Но как насчет этого места для ласки? Ну, когда вы передаете A
и C
функции сортировки, вы могли бы закодировать существование B
в состоянии A
A = {
"type": "PICKUP"
, "peer": B
, "distance": 5
}
B = {
"type": "DROPOFF"
, "peer": "A"
, "distance": 1
}
// ...
Теперь вы можете написать свою функцию сравнения, чтобы учитывать значение расстояния B
при сравнении A
с C
. Но обратите внимание, что сравнение все еще не работает с контекстом, который ‘ B
также находится в списке - and in fact, this will behave the same *whether or not
B is in the list*, because you have set
A to a state which, according to your own rules, implies that
B` должен быть в списке.
Но это возвращает нас к тому же вопросу…
Причина, по которой я продолжаю приводить пример, заключается в том, что, как только придет время устранить эти расхождения, есть несколько способов сделать это, что приведет к очень разным порядкам расположения узлов. И вам нужно подумать о том, как вы хотите, чтобы они были разрешены достаточно подробно, чтобы предоставить запрошенный пример, И как только вы это сделаете, вам, возможно, больше не понадобится предоставлять пример, потому что решение, скорее всего, появится само.
Что я подозреваю, вам нужно будет сделать, так это отсортировать только подборки, затем пройтись по списку, на каждом узле определяя, лучше ли перейти к следующей подборке или завершить одно из отбрасываний для того, что вы уже подобрали.
Или, может быть, у вас есть какое-то согласованное правило, с помощью которого вы можете сравнить, например, данную отправку (и соответствующее ей удаление) с несвязанной отправкой (и соответствующим ей получением) и получить из этого стабильные / согласованные значения порядка.
Но с учетом приведенной информации это всего лишь предположения.
Комментарии:
1. Спасибо за ваш отзыв и за приветствие. Дайте мне знать, если это те примеры, которые вам требовались, которые соответствуют ожидаемым и фактическим результатам при использовании функций выше. Есть какие-нибудь мысли о том, как, как вы говорите, отсортировать пикапы, а затем определить на каждом узле, следует ли переходить к следующему пикапу или удалению?
2. Пожалуйста, также проверьте мои результаты для последней функции, которая у меня есть в исходном вопросе. Он может сортировать выборки, но все равно потребуется некоторый тип метода forEach для сравнения каждой выборки.
Ответ №2:
Я думаю, что наконец-то понял это. Я изменил свою последнюю функцию, добавил сращивание и тип пузырьковой сортировки. Это может помочь следующему пользователю.
var newTab = [], newTaby = [];
for(var i = 0, iLimit = array.length; i < iLimit; i ) {
if(array[i].buyerId) {
newTaby.push(array[i]);
} else {
newTab.push(array[i]);
}
}
newTab.sort((a,b) => {
var aVal = parseInt(a.distance);
var bVal = parseInt(b.distance);
if (aVal===bVal) {
return 0;
} else {
return aVal < bVal ? -1 : 1;
}
});
for(let k = 0; k < newTaby.length; k ){
for(let j = 0; j < newTab.length; j ) {
if(newTaby[k].key5 == newTab[j].key5){
newTab.splice(j 1, 0, newTaby[k])
break;
}
}
}
for(let h=0; h < newTab.length - 1; h ) {
for(let x=h 1; x < newTab.length; x ) {
if (newTab[h].key4 != newTab[x].key4 amp;amp; parseFloat(newTab[h].distance) >
parseFloat(newTab[x].distance) amp;amp; newTab[h].log == '1'){
let theGreater = newTab[h];
newTab[h] = newTab[x];
newTab[x] = theGreater;
}
}
}
console.log(newTab) //this will give the sorted array
Спасибо, что направили меня в правильном направлении! @Отметить