Сортировать массив по расстоянию и иметь некоторые индексы относительно друг друга

#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
  

Спасибо, что направили меня в правильном направлении! @Отметить