Сортировать массив по расстоянию и иметь некоторые индексы относительно друг друга - PullRequest
0 голосов
/ 07 марта 2019

У меня есть массив объектов:

  • A: ПИКАП А С РАССТОЯНИЕМ 9,96
  • Б: УДАЛЕНИЕ А С РАССТОЯНИЕМ 13,46
  • С: ПИКАП 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: DROPOFF B с расстоянием 1,06
  • D: PICKUP A с расстоянием 9,96
  • E: DROPOFF A с расстоянием 13,46
  • F: DROPOFF C с расстоянием 17,86

Я тщетно пытался сначала отсортировать по расстоянию, но все еще имею, где «key4» одного объекта равно «key4» другого объекта, а затем, если «log» первого объекта большечем второй «log», то тот, что «log 2», помещается выше.Неважно, где находится второй объект, если он находится ниже первого объекта, где все объекты соблюдают сортировку по расстоянию.Я хотел бы закончить с CEDABF.Я хотел бы для пары подходящих объектов, чтобы Pickup всегда был перед Dropoff, независимо от разницы расстояний, но Pickup не должен быть непосредственно перед этим Dropoff.Порядок может быть Pickup1, Dropoff1, Pickup2, Pickup3, Dropoff3, Dropoff2, и это основано на расстоянии.Здесь Dropoff2 идет после Pickup2, но не сразу после него.До сих пор я был в состоянии сортировать по возрастанию расстояния, но тогда критерии игнорируются, и аналогично, если, если я сортирую по key4 и log, то расстояние игнорируется.Любая помощь будет признательна.

Это то, что я пытался:

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

И это дает:

  • A: DROPOFF B с расстоянием 1,06
  • B: Пикап C с расстоянием 3.86
  • C: Пикап B с расстоянием 4.46
  • D: Пикап A с расстоянием 9.96
  • E: СНИЖЕНИЕ A С ДИСТАНЦИИ13,46
  • F: DROPOFF C С РАССТОЯНИЕМ 17,86

    0: {имя: "C" расстояние: "1,06" key4: "ggg" log: "2" тип: "Dropoff"}

    1: {имя:" E "расстояние:" 3,86 "key4:" jjj "log:" 2 "тип:" Pickup "}

    2: {name:" D"distance:" 4.46 "key4:" ggg "key5:" true "log:" 1 "тип:" Pickup "}

    3: {name:" A "расстояние:" 9.96 "key4:" zzz"log:" 2 "тип:" Pickup "}

    4: {name:" B "расстояние:" 13.46 "key4:" zzz "key5:" true "log:" 1 "тип:" Dropoff"}

    5: {name:" F "расстояние:" 17.86 "key4:" jjj "key5:" true "log:" 1 "тип:" Dropoff "}

Это только сортирует расстояния, но игнорирует "key4" и "idx", так чтоDropoff (DROPOFF B) с ключом 4 = "ggg" перед соответствующим пикапом.

Я также пробовал:

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

Это дает мне тот же результат, что и выше:

  • A: СБРОС B С РАССТОЯНИЕМ 1.06
  • B: ПИКАП C С РАССТОЯНИЕМ 3.86
  • C: ПИКАП B С РАССТОЯНИЕМ 4.46
  • D: ПИКАП А С РАССТОЯНИЕМ 9.96
  • E: СБРОС A С ДИСТАНЦИИ 13.46
  • F: СБРОС C С ДИСТАНЦИЕЙ 17.86

    0: {name: расстояние "C": "1.06" key4:журнал "ggg": тип "2": "Dropoff"}

    1: {имя: "E" расстояние: "3.86" ключ4: "jjj" журнал: тип "2": "пикап"}

    2: {имя: «D» расстояние: «4,46» key4: «ggg» key5: «true» log: «1» тип: «Pickup»}

    3: {name:«A» расстояние: «9,96» key4: «zzz» log: «2» тип: «Pickup»}

    4: {name: «B» расстояние: «13.46» key4: «zzz» key5:«true» log: «1» тип: «Dropoff»}

    5: {name: «F» расстояние: «17,86» key4: «jjj» key5: «true» log: «1» тип:"Dropoff"}

Это толькосортирует «key4», если два расстояния равны.

Наконец, я попытался добавить атрибут «customerId» для каждого объекта Dropoff. :

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

Число после сращивания просто показывает, как будет вставляться Dropoffs. Пикапы сортируются по расстоянию до тех пор, пока не будет выполнена вставка, а затем продолжают сортировку. Это дает мне:

  • A: Пикап C с расстоянием 3,86
  • B: Пикап B с расстоянием 4.46
  • C: СБРОС B С РАССТОЯНИЕМ 1.06
  • D: сбросить с расстояния 13,46
  • E: СБРОС C С РАССТОЯНИЕМ 17,86
  • E: Пикап с расстоянием 9,96

Ответы [ 2 ]

0 голосов
/ 09 марта 2019

Я думаю, что наконец-то понял. Я изменил свою последнюю функцию, добавил сплайс и тип пузырьковой сортировки. Это может помочь следующему человеку.

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 && parseFloat(newTab[h].distance) > 
    parseFloat(newTab[x].distance) && newTab[h].log == '1'){
      let theGreater = newTab[h];
      newTab[h] = newTab[x]; 
      newTab[x] = theGreater;
     }
   }
}

console.log(newTab) //this will give the sorted array

Спасибо за руководство в правильном направлении! @ Mark

0 голосов
/ 07 марта 2019

ОБНОВЛЕНИЕ - Я обнаружил некоторую "серую область" вокруг ограничений, которые я цитирую для метода sort, который я разъясняю ...


Добро пожаловать в переполнение стека.

Основываясь на обсуждении в комментариях, у меня есть более четкое представление о том, что вы пытаетесь сделать.Тем не менее, ключевой элемент высококачественного вопроса заключается в том, что в нем есть пример, демонстрирующий ожидаемое поведение ( и показывают, как это поведение отличается от результатов, полученных при использовании методов).В настоящее время я вижу один пример, который не демонстрирует никакой разницы в результатах «сортировки по расстоянию».Хотя вы отдельно описываете, почему «сортировка по расстоянию» - это не то, что вам нужно, должен быть представлен пример, демонстрирующий эту разницу.

Поскольку такого примера нет (даже после того, как один был запрошен), я 'Я предоставлю большую часть ответа с предоставленной информацией, насколько это возможно, но это будет сопровождаться напоминанием о том, что в SO качество ответов будет зависеть от качества вопроса.


Итак, что яМожно определенно сказать, что вы сталкиваетесь с границами того, что может сделать метод sort.

Когда вы предоставляете функцию упорядочения для sort, она должна иметь возможность смотреть на любые два элемента и говорить «этот должен идти раньше этого», без необходимости контекста (например, является ли 3-й элементсоответствие определенным критериям может существовать).(В некоторых случаях есть небольшое пространство, чтобы обойти это ограничение, о котором я расскажу через минуту.)

Так, например, если у вас было

  • A: ПИКАП А С ДИСТАНЦИЕЙ 5
  • B: СНИЖЕНИЕ А С ДИСТАНЦИЕЙ 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` должно быть в списке.

Но это возвращает нас к одной и той же точке ...

Причина, по которой я продолжаю использовать пример, состоит в том, что, как только пришло время устранить эти расхождения, есть несколько способов сделать это, что приводит кочень разные порядки узлов.И вам нужно , чтобы подумать о том, как вы хотите, чтобы те, которые были решены, были достаточно подробны, чтобы предоставить запрошенный пример. И как только вы это сделаете, вам больше не нужно будет предоставлять пример, потому что решение, скорее всего, представит себя.*

Что я подозреваю вам нужно сделать, это отсортировать только пикапы, затем пройтись по списку, на каждом узле, определяя, лучше ли переходить к следующему пикапу или завершить одно из выпаденийдля чего-то, что вы уже подобрали.

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

Но с учетом данной информации, это только предположение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...