按距离对数组进行排序,并且彼此之间有一些索引

时间:2019-03-07 18:15:35

标签: javascript sorting ionic-framework

我有一个对象数组:

  • A:距离A达9.96
  • B:距离D的距离为13.46
  • C:距离B的距离为4.46
  • D:距离B下降1.06
  • E:以3.86的距离拾取C
  • 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:距离3.86的皮卡C
  • B:距离B的距离为4.46
  • C:距离B下降1.06
  • D:以9.96的距离拾取A
  • E:距离D的距离为13.46
  • F:距离C下降17.86

我一直在徒劳地尝试按距离进行排序,但是仍然有一个对象的“ key4”等于另一个对象的“ key4”的位置,然后如果第一个对象的“ 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
           })

这给出了:

  • A:距离B下降1.06
  • B:以3.86的距离拾取C
  • C:距离B的距离为4.46
  • D:以9.96的距离拾取A
  • E:距离D的距离为13.46
  • F:距离C下降为17.86

    0:{     名称:“ C”     距离:“ 1.06”     key4:“ ggg”     日志:“ 2”     类型:“ Dropoff” }

    1:{    名称:“ E”    距离:“ 3.86”    key4:“ jjj”    日志:“ 2”    类型:“提取” }

    2:{        名称:“ D”        距离:“ 4.46”        key4:“ ggg”        key5:“ true”        日志:“ 1”        类型:“提取”     }

    3:{    名称:“ A”    距离:“ 9.96”    key4:“ zzz”    日志:“ 2”    类型:“提取” }

    4:{    名称:“ B”    距离:“ 13.46”    key4:“ zzz”    key5:“ true”    日志:“ 1”    类型:“ Dropoff” }

    5:{    名称:“ F”    距离:“ 17.86”    key4:“ jjj”    key5:“ true”    日志:“ 1”    类型:“ Dropoff” }

这仅对距离进行排序,但忽略“ key4”和“ idx”,因此具有key4 =“ ggg”的Dropoff(DROPOFF B)在其对应的拾取之前。

我也尝试过:

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:以3.86的距离拾取C
  • C:距离B的距离为4.46
  • D:以9.96的距离拾取A
  • E:距离D的距离为13.46
  • F:距离C下降为17.86

    0:{     名称:“ C”     距离:“ 1.06”     key4:“ ggg”     日志:“ 2”     类型:“ Dropoff” }

    1:{    名称:“ E”    距离:“ 3.86”    key4:“ jjj”    日志:“ 2”    类型:“提取” }

    2:{    名称:“ D”    距离:“ 4.46”    key4:“ ggg”    key5:“ true”    日志:“ 1”    类型:“提取” }

    3:{    名称:“ A”    距离:“ 9.96”    key4:“ zzz”    日志:“ 2”    类型:“提取” }

    4:{    名称:“ B”    距离:“ 13.46”    key4:“ zzz”    key5:“ true”    日志:“ 1”    类型:“ Dropoff” }

    5:{    名称:“ F”    距离:“ 17.86”    key4:“ jjj”    key5:“ true”    日志:“ 1”    类型:“ Dropoff” }

仅当两个距离相等时才对“ key4”进行排序。

最后,我尝试是否在每个Dropoff对象上添加了一个“ 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]);
}

拼接后的数字仅用于显示Dropoffs如何插入。拾取器按距离排序,直到插入为止,然后继续进行排序。 这给了我

  • A:距离3.86的皮卡C
  • B:距离B的距离为4.46
  • C:距离B下降1.06
  • D:距离D的距离为13.46
  • E:距离C下降17.86
  • E:以9.96的距离接A

2 个答案:

答案 0 :(得分:0)

更新-我已经阐明了sort方法所带来的局限性,这是一个“灰色地带”,我正在澄清...


欢迎堆栈溢出。

基于评论中的讨论,我对您要尝试的内容有更清晰的了解。就是说,高质量问题的关键要素是它有一个示例,该示例显示了预期的行为(表明该行为与尝试的方法的结果有何不同)。目前,我看到一个示例,该示例并未显示“按距离排序”的结果有何不同。尽管您分别描述了为什么“按距离排序”不是您想要的,但是应该提供一个示例来证明这种差异。

由于没有这样的示例(即使请求了一个示例),我也会根据给定的信息尽可能多地提供答案,但这提醒我们,答案的质量会提高取决于问题的质量。


所以我可以肯定地说的是,您正在遇到股票sort方法可能能够完成的工作。

当您为sort提供排序功能时,它必须能够查看任意两个元素并说“此元素应该先于该元素”,而无需上下文(例如是否满足第三个元素)可能存在特定条件)。 (在某些情况下,有一个的空间可以缓解这种限制,我将在稍后讨论。)

例如,如果您有

  • A:距离5的A
  • B:以距离1离开A
  • C:距离B的拾取3

赋予sort的比较功能必须能够查看BC,并且在不知道A存在或不存在的情况下,决定是否B在列表中排在C之前。同样,它必须能够在不了解A的情况下比较CB。结果必须是一致的,例如,如果它说x>yy>z,那么它也必须说x>z

仅看AC,看来C应该排在第一位。

仅看BC,看来B应该排在第一位。

看看AB,我们知道A必须排在第一位。

A > C > B > A

因此,sort算法没有适用的一致排序规则。

但是那个哭泣的空间呢?好吧,当您将AC传递给sort函数时,您可以可以编码BA状态下的存在

A = {
  "type": "PICKUP"
, "peer": B
, "distance": 5
}

B = {
  "type": "DROPOFF"
, "peer": "A"
, "distance": 1
}

// ...

现在,您可以编写比较函数来比较BAC的距离值。但是请注意,比较 still 并不是在'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的上下文中进行的`应该在​​列表中。

但这使我们回到了同一点...

我一直在举一个例子的原因是,一旦是时候解决这些差异了,有多种方法可以解决这个问题,从而导致节点的排列顺序大不相同。然后,您需要考虑如何使解决的细节足够详细,以提供所请求的示例。一旦完成,您可能就不再需要提供示例了,因为解决方案很可能会自我展示。 / p>

怀疑您需要做的是,仅对拾音器进行排序,然后遍历列表,在每个节点处确定是进行下一个拾音器还是完成下一个拾音器是最佳选择为您已经拿起的东西。

或者您可能有一些一致的规则,例如,您可以将给定的取件(及其对应的取件)与不相关的取件(及其对应的取件)进行比较,并产生稳定/一致的订购值从那开始。

但是有了给定的信息,这些仅仅是推测。

答案 1 :(得分:0)

我想我终于明白了。我更改了我的最后一个功能,添加了拼接和一种冒泡排序。这可能会帮助下一个人。

Token

感谢您引导我朝正确的方向前进! @Mark