【问题标题】:Matching Objects in Array and Consolidate匹配数组中的对象并合并
【发布时间】:2018-10-21 00:56:11
【问题描述】:

更新:

我有一个名为 cars 的对象数组,其中包含带有汽车属性数据(例如价格、汽车类型等)的 li 标签。我的目标是将这些汽车合并到一个列表中(如果它们基于特定标准匹配)。

要求

  1. 快速性能
  2. 保持相同的汽车数组结构
  3. 主要目标: 匹配预付费列表和零售列表 - 将零售列表中的 HTML(例如按钮和定价信息)合并到预付费列表中。见:
  4. 如果存在匹配项(基于 IF 语句中的条件),则删除没有“listing-prepaid”类的匹配列表,并使用零售列表中的某些信息更新匹配的预付费列表。

汽车阵列:

<li xmlns="http://www.w3.org/1999/xhtml" id="listing-CCAR-RM-AD-SFBT003-AD-SFBT003" data-location-id="AD-28.7455--81.2411" data-dropoff-location-id="AD-28.7455--81.2411" data-partner-name="Advantage" data-partner-code="AD" data-type="CCAR" data-vehicle-class-description="Compact Car" data-seats="5" data-bags="2" data-counter-type="ON_AIRPORT" data-prepaid="Y" data-fare-type="PREPAID" data-transmission="Automatic" data-unlimited-miles="Y" data-preferred="N" data-price="34.81" data-original-price="35.70" data-base-price="24.25" data-vehicle-example="Nissan Versa" data-highlighted="N" data-deal="Y" class="listing listing-prepaid" data-original-position="18"><div class="row"><div class="column column-images"><div class="img-wrapper"><ul class="icons"><li class="people"><span>5</span></li><li class="bags"><span>2</span></li></ul></div></div><div class="column car-details"><div class="car-title"><h3><a><span class="car-class">Compact</span><b></b></a></h3><span class="car-example">Nissan Versa or similar<sup>†</sup></span><span class="counter-type airport">Car on Airport</span></div><div class="features"><span>Unlimited Miles</span></div><div class="car-location-container"><div class="car-location"><h6>Pick-up</h6>SFB: Orlando Sanford Intl Airport</div><div class="car-location"><h6>Drop-off</h6>Same as pick-up</div></div></div><div class="column column-price"><span class="car-badge prepaid">Pay Now &amp; Save 2%</span><div class="container retail prepaid"><div class="rate"><span class="strikethrough"><span class="price-original">$25</span></span><span class="cur-symbol">$</span><span class="price">24</span><span class="rate-plan">/day</span></div><p class="button"><a class="button">Pay Now</a></p><span class="total">Total: $<span class="price">34</span></span></div></div></div><b style="clear:both;display:block;height:1px;width:1px"></b></li>

<li xmlns="http://www.w3.org/1999/xhtml" id="listing-ECAR-RP-HZ-ORLN003-HZ-ORLN003" data-location-id="HZ-28.5042--81.4284" data-dropoff-location-id="HZ-28.5042--81.4284" data-partner-name="Hertz" data-partner-code="HZ" data-type="ECAR" data-vehicle-class-description="Economy Car" data-seats="4" data-bags="1" data-counter-type="" data-prepaid="Y" data-fare-type="PREPAID" data-transmission="Automatic" data-unlimited-miles="Y" data-preferred="N" data-price="36.34" data-original-price="39.95" data-base-price="29.83" data-vehicle-example="Chevrolet Spark" data-highlighted="N" data-deal="Y" class="listing listing-prepaid" data-original-position="30"><div class="row"><div class="column column-images"><div class="img-wrapper"><ul class="icons"><li class="people"><span>4</span></li><li class="bags"><span>1</span></li></ul></div></div><div class="column car-details"><div class="car-title"><h3><a><span class="car-class">Economy</span><b></b></a></h3><span class="car-example">Chevrolet Spark or similar<sup>†</sup></span></div><div class="features"><span>Unlimited Miles</span></div><div class="car-location-container"><div class="car-location"><h6>Pick-up</h6>3575 Vineland Road, Orlando, FL</div><div class="car-location"><h6>Drop-off</h6>Same as pick-up</div></div></div><div class="column column-price"><span class="car-badge prepaid">Pay Now &amp; Save 9%</span><div class="container retail prepaid"><div class="rate"><span class="strikethrough"><span class="price-original">$33</span></span><span class="cur-symbol">$</span><span class="price">29</span><span class="rate-plan">/day</span></div><p class="button"><a class="button">Pay Now</a></p><span class="total">Total: $<span class="price">36</span></span></div></div></div><b style="clear:both;display:block;height:1px;width:1px"></b></li>

<li xmlns="http://www.w3.org/1999/xhtml" id="listing-CCAR-R-AD-SFBT003-AD-SFBT003" data-location-id="AD-28.7455--81.2411" data-dropoff-location-id="AD-28.7455--81.2411" data-partner-name="Advantage" data-partner-code="AD" data-type="CCAR" data-vehicle-class-description="Compact Car" data-seats="5" data-bags="2" data-counter-type="ON_AIRPORT" data-prepaid="N" data-fare-type="RETAIL" data-transmission="Automatic" data-unlimited-miles="Y" data-preferred="N" data-price="35.70" data-base-price="25.00" data-vehicle-example="Nissan Versa" data-highlighted="N" data-deal="N" class="listing" data-original-position="22"><div class="row"><div class="column column-images"><div class="img-wrapper"><ul class="icons"><li class="people"><span>5</span></li><li class="bags"><span>2</span></li></ul></div></div><div class="column car-details"><div class="car-title"><h3><a><span class="car-class">Compact</span><b></b></a></h3><span class="car-example">Nissan Versa or similar<sup>†</sup></span><span class="counter-type airport">Car on Airport</span></div><div class="features"><span>Free Cancellation</span><span>Pay at Pick-up</span><span>Unlimited Miles</span></div><div class="car-location-container"><div class="car-location"><h6>Pick-up</h6>SFB: Orlando Sanford Intl Airport</div><div class="car-location"><h6>Drop-off</h6>Same as pick-up</div></div></div><div class="column column-price"><div class="container retail"><div class="rate"><span class="cur-symbol">$</span><span class="price">25</span><span class="rate-plan">/day</span></div><p class="button"><a class="button">Select Car</a></p><span class="total">Total: $<span class="price">35</span></span></div></div></div><b style="clear:both;display:block;height:1px;width:1px"></b></li>

<li xmlns="http://www.w3.org/1999/xhtml" id="listing-ECAR-R-EX-MCOO001-EX-MCOO001" data-location-id="EX-28.4514095--81.3577729" data-dropoff-location-id="EX-28.4514095--81.3577729" data-partner-name="Executive" data-partner-code="EX" data-type="ECAR" data-vehicle-class-description="Economy Car" data-seats="2" data-bags="1" data-counter-type="OFF_AIR_SHTL" data-prepaid="N" data-fare-type="RETAIL" data-transmission="Automatic" data-unlimited-miles="Y" data-preferred="N" data-price="28.78" data-base-price="14.58" data-vehicle-example="SmartCar" data-highlighted="N" data-deal="N" class="listing" data-original-position="2"><div class="row"><div class="column column-images"><div class="img-wrapper"><ul class="icons"><li class="people"><span>2</span></li><li class="bags"><span>1</span></li></ul></div></div><div class="column car-details"><div class="car-title"><h3><a><span class="car-class">Economy</span><b></b></a></h3><span class="car-example">SmartCar or similar<sup>†</sup></span><span class="counter-type shuttle">Shuttle to Car</span></div><div class="features"><span>Pay at Pick-up</span><span>Unlimited Miles</span></div><div class="car-location-container"><div class="car-location"><h6>Pick-up</h6>MCO: Orlando Intl Airport</div><div class="car-location"><h6>Drop-off</h6>Same as pick-up</div></div></div><div class="column column-price"><div class="container retail"><div class="rate"><span class="cur-symbol">$</span><span class="price">14</span><span class="rate-plan">/day</span></div><p class="button"><a class="button">Select Car</a></p><span class="total">Total: $<span class="price">28</span></span></div></div></div><b style="clear:both;display:block;height:1px;width:1px"></b></li>

预期输出:

在上面的示例数组中,第一个和第三个列表应该是匹配的(因为它们具有相同的汽车类型、位置 ID、车辆示例等)。第一个列表应该从数组中删除,因为它没有类 Listing-prepaid 并且 .column-price 中的 HTML 应该添加到它的预付费匹配中(在这个例子中,数组中的第三个列表)。

最终产品:

代码:

 cars = cars.reduce((acc, car) => {
    let retail_match = false;
    cars.forEach(car2 => {

        if (((car[0].hasAttribute("data-original-price") && car[0].getAttribute("data-original-price") === car2[0].getAttribute("data-price")) || (car2[0].hasAttribute("data-original-price") && car2[0].getAttribute("data-original-price") === car[0].getAttribute("data-price"))) && (car[0].getAttribute("data-base-price") != car2[0].getAttribute("data-base-price")) && (car[0].getAttribute("data-price") != car2[0].getAttribute("data-price")) && (car[0].getAttribute("data-type") == car2[0].getAttribute("data-type")) && (car[0].getAttribute("data-vehicle-example") == car2[0].getAttribute("data-vehicle-example")) && (car[0].getAttribute("data-location-id") == car2[0].getAttribute("data-location-id")) && (car[0].getAttribute("data-dropoff-location-id") == car2[0].getAttribute("data-dropoff-location-id")))
        {
            if (!car.hasClass("listing-prepaid"))
                retail_match = true;
            else
            {
                car.find(".column-price")
                    .addClass("prepaid-match")
                    .append(car2.find(".column-price div.retail"))
                    .find("div.retail:not(.prepaid) p.button a").text("Pay Later");
            }
        }
    });
    if (!retail_match)
        acc.push(car);
    return acc;
}, []);

【问题讨论】:

  • car 不是一个数组,所以car[0] 不应该工作,只使用car ...如果我在这里没有遗漏什么,car2[0] 也应该如此
  • 我认为使用 reduce 比 filter 更有意义。

标签: javascript jquery arrays object


【解决方案1】:

如 cmets 中所述,使用 reduce 将复杂度保持在 O(n)。这基本上意味着,两倍大小的列表将花费两倍的时间,因为该算法只迭代汽车列表一次。

如果您需要将汽车数组中的每个项目与汽车数组中的其他项目进行比较,使用类似循环的方法的复杂度将不会 O(n^2),因为对于每一个额外的item(粗略地说)将使用成倍增加的循环/时间。

我不能 100% 确定您的 javascript 对象的数据结构,但以下方法应该可行:

const allCars = []; // An array of cars, each item is a HTMLElement
let matchedCars = allCars.reduce((acc, car, cars) => {

   cars.forEach(car2 => {
       // For every car iterate over the cars array again to compare car to every item in the cars array (leave out this loop if you don't need the extensive comparison)

       if (car.hasAttribute("data-original-price") 
           && car2.getAttribute("data-original-price") === car.getAttribute("data-price")
          /* Add additional matching criteria here, you may access cars to get info about other cars than the current car */) {

            // Add the desired class for a match
            car.classList.add('listing-prepaid');

            // Add the matched car to the accumulator, so it ends up in the matchedCars array
            acc.push(car);
      }

   });
}, [];

另一种方法是构建一个数据结构,允许在恒定时间内根据元素的属性访问元素 (O(1))。一个例子是(Hash)Map。在这种情况下,对于算法循环遍历的每个元素,不需要再次遍历整个列表来识别匹配项,而是查询 Map 结构中的匹配项。

奖励:鉴于 car 是一个 HTMLElement,您可以使用 dataset 属性来访问 data-* em> 值更容易:

car.dataset.originalPrice === car.dataset.price

https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes了解更多信息

一般来源:https://developer.mozilla.org/en-US/docs/Web/API/HTMLElementhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

【讨论】:

  • 感谢您的回复!如果我使用reduce,我不需要forEach吗?我如何看待一辆车的数据价格 === 另一辆车的数据原始价格?
  • 不需要 forEach。 reduce 遍历汽车列表并将所有匹配的汽车推入 acc 数组,该数组将从 reduce 方法返回。请参阅调整后的答案代码,了解如何获取汽车数组中的其他汽车
  • 啊,好吧。我看到你添加了另一个参数汽车来减少功能?因此,如果我想检查 car.data("price") == originalPrice of other car...我会检查 car.data("price") == cars.data("originalPrice")?
  • 不幸的是,这在您的问题中没有明确说明。这需要在 reduce 函数中对整个汽车数组进行额外的循环。您可以为此使用 forEach。
  • 非常感谢您的帮助!我已经用更明确的要求更新了帖子。希望它现在更有意义!
【解决方案2】:

代码中有一个错误,例如,当您从 js 中的数组访问 HTML 元素时,它返回字符串而不是 HTML 对象,因此您无法访问它意味着您无法应用 JS/Jquery hasAttribute 和其他上面的功能,我已经修复了,你可以在 fiddle 上找到工作示例,链接如下:

    var cars = ['<li xmlns="http://www.w3.org/1999/xhtml" id="listing-CCAR-RM-AD-SFBT003-AD-SFBT003" data-location-id="AD-28.7455--81.2411" data-dropoff-location-id="AD-28.7455--81.2411" data-partner-name="Advantage" data-partner-code="AD" data-type="CCAR" data-vehicle-class-description="Compact Car" data-seats="5" data-bags="2" data-counter-type="ON_AIRPORT" data-prepaid="Y" data-fare-type="PREPAID" data-transmission="Automatic" data-unlimited-miles="Y" data-preferred="N" data-price="34.81" data-original-price="35.70" data-base-price="24.25" data-vehicle-example="Nissan Versa" data-highlighted="N" data-deal="Y" class="listing listing-prepaid" data-original-position="18"><div class="row"><div class="column column-images"><div class="img-wrapper"><ul class="icons"><li class="people"><span>5</span></li><li class="bags"><span>2</span></li></ul></div></div><div class="column car-details"><div class="car-title"><h3><a><span class="car-class">Compact</span><b></b></a></h3><span class="car-example">Nissan Versa or similar<sup>†</sup></span><span class="counter-type airport">Car on Airport</span></div><div class="features"><span>Unlimited Miles</span></div><div class="car-location-container"><div class="car-location"><h6>Pick-up</h6>SFB: Orlando Sanford Intl Airport</div><div class="car-location"><h6>Drop-off</h6>Same as pick-up</div></div></div><div class="column column-price"><span class="car-badge prepaid">Pay Now &amp; Save 2%</span><div class="container retail prepaid"><div class="rate"><span class="strikethrough"><span class="price-original">$25</span></span><span class="cur-symbol">$</span><span class="price">24</span><span class="rate-plan">/day</span></div><p class="button"><a class="button">Pay Now</a></p><span class="total">Total: $<span class="price">34</span></span></div></div></div><b style="clear:both;display:block;height:1px;width:1px"></b></li>', '<li xmlns="http://www.w3.org/1999/xhtml" id="listing-ECAR-RP-HZ-ORLN003-HZ-ORLN003" data-location-id="HZ-28.5042--81.4284" data-dropoff-location-id="HZ-28.5042--81.4284" data-partner-name="Hertz" data-partner-code="HZ" data-type="ECAR" data-vehicle-class-description="Economy Car" data-seats="4" data-bags="1" data-counter-type="" data-prepaid="Y" data-fare-type="PREPAID" data-transmission="Automatic" data-unlimited-miles="Y" data-preferred="N" data-price="36.34" data-original-price="39.95" data-base-price="29.83" data-vehicle-example="Chevrolet Spark" data-highlighted="N" data-deal="Y" class="listing listing-prepaid" data-original-position="30"><div class="row"><div class="column column-images"><div class="img-wrapper"><ul class="icons"><li class="people"><span>4</span></li><li class="bags"><span>1</span></li></ul></div></div><div class="column car-details"><div class="car-title"><h3><a><span class="car-class">Economy</span><b></b></a></h3><span class="car-example">Chevrolet Spark or similar<sup>†</sup></span></div><div class="features"><span>Unlimited Miles</span></div><div class="car-location-container"><div class="car-location"><h6>Pick-up</h6>3575 Vineland Road, Orlando, FL</div><div class="car-location"><h6>Drop-off</h6>Same as pick-up</div></div></div><div class="column column-price"><span class="car-badge prepaid">Pay Now &amp; Save 9%</span><div class="container retail prepaid"><div class="rate"><span class="strikethrough"><span class="price-original">$33</span></span><span class="cur-symbol">$</span><span class="price">29</span><span class="rate-plan">/day</span></div><p class="button"><a class="button">Pay Now</a></p><span class="total">Total: $<span class="price">36</span></span></div></div></div><b style="clear:both;display:block;height:1px;width:1px"></b></li>', '<li xmlns="http://www.w3.org/1999/xhtml" id="listing-CCAR-R-AD-SFBT003-AD-SFBT003" data-location-id="AD-28.7455--81.2411" data-dropoff-location-id="AD-28.7455--81.2411" data-partner-name="Advantage" data-partner-code="AD" data-type="CCAR" data-vehicle-class-description="Compact Car" data-seats="5" data-bags="2" data-counter-type="ON_AIRPORT" data-prepaid="N" data-fare-type="RETAIL" data-transmission="Automatic" data-unlimited-miles="Y" data-preferred="N" data-price="35.70" data-base-price="25.00" data-vehicle-example="Nissan Versa" data-highlighted="N" data-deal="N" class="listing" data-original-position="22"><div class="row"><div class="column column-images"><div class="img-wrapper"><ul class="icons"><li class="people"><span>5</span></li><li class="bags"><span>2</span></li></ul></div></div><div class="column car-details"><div class="car-title"><h3><a><span class="car-class">Compact</span><b></b></a></h3><span class="car-example">Nissan Versa or similar<sup>†</sup></span><span class="counter-type airport">Car on Airport</span></div><div class="features"><span>Free Cancellation</span><span>Pay at Pick-up</span><span>Unlimited Miles</span></div><div class="car-location-container"><div class="car-location"><h6>Pick-up</h6>SFB: Orlando Sanford Intl Airport</div><div class="car-location"><h6>Drop-off</h6>Same as pick-up</div></div></div><div class="column column-price"><div class="container retail"><div class="rate"><span class="cur-symbol">$</span><span class="price">25</span><span class="rate-plan">/day</span></div><p class="button"><a class="button">Select Car</a></p><span class="total">Total: $<span class="price">35</span></span></div></div></div><b style="clear:both;display:block;height:1px;width:1px"></b></li>', '<li xmlns="http://www.w3.org/1999/xhtml" id="listing-ECAR-R-EX-MCOO001-EX-MCOO001" data-location-id="EX-28.4514095--81.3577729" data-dropoff-location-id="EX-28.4514095--81.3577729" data-partner-name="Executive" data-partner-code="EX" data-type="ECAR" data-vehicle-class-description="Economy Car" data-seats="2" data-bags="1" data-counter-type="OFF_AIR_SHTL" data-prepaid="N" data-fare-type="RETAIL" data-transmission="Automatic" data-unlimited-miles="Y" data-preferred="N" data-price="28.78" data-base-price="14.58" data-vehicle-example="SmartCar" data-highlighted="N" data-deal="N" class="listing" data-original-position="2"><div class="row"><div class="column column-images"><div class="img-wrapper"><ul class="icons"><li class="people"><span>2</span></li><li class="bags"><span>1</span></li></ul></div></div><div class="column car-details"><div class="car-title"><h3><a><span class="car-class">Economy</span><b></b></a></h3><span class="car-example">SmartCar or similar<sup>†</sup></span><span class="counter-type shuttle">Shuttle to Car</span></div><div class="features"><span>Pay at Pick-up</span><span>Unlimited Miles</span></div><div class="car-location-container"><div class="car-location"><h6>Pick-up</h6>MCO: Orlando Intl Airport</div><div class="car-location"><h6>Drop-off</h6>Same as pick-up</div></div></div><div class="column column-price"><div class="container retail"><div class="rate"><span class="cur-symbol">$</span><span class="price">14</span><span class="rate-plan">/day</span></div><p class="button"><a class="button">Select Car</a></p><span class="total">Total: $<span class="price">28</span></span></div></div></div><b style="clear:both;display:block;height:1px;width:1px"></b></li>'];
cars = cars.reduce((acc, car) => {
  let retail_match = false;
  cars.forEach(car2 => {

    if ((($(car)[0].hasAttribute("data-original-price") && $(car)[0].getAttribute("data-original-price") === $(car2)[0].getAttribute("data-price")) || ($(car2)[0].hasAttribute("data-original-price") && $(car2)[0].getAttribute("data-original-price") === $(car)[0].getAttribute("data-price"))) && ($(car)[0].getAttribute("data-base-price") != $(car2)[0].getAttribute("data-base-price")) && ($(car)[0].getAttribute("data-price") != $(car2)[0].getAttribute("data-price")) && ($(car)[0].getAttribute("data-type") == $(car2)[0].getAttribute("data-type")) && ($(car)[0].getAttribute("data-vehicle-example") == $(car2)[0].getAttribute("data-vehicle-example")) && ($(car)[0].getAttribute("data-location-id") == $(car2)[0].getAttribute("data-location-id")) && ($(car)[0].getAttribute("data-dropoff-location-id") == $(car2)[0].getAttribute("data-dropoff-location-id"))) {
      if (!$(car).hasClass("listing-prepaid"))
        retail_match = true;
      else {
        $(car).find(".column-price")
          .addClass("prepaid-match")
          .append($(car2).find(".column-price div.retail"))
          .find("div.retail:not(.prepaid) p.button a").text("Pay Later");
      }

      console.log(retail_match);
    }
  });
  if (!retail_match)
    acc.push(car);
  return acc;
}, []);

console.log(cars);

[jsfiddle][1]


I hope this will solve your issue, Let me know if you've any question. Thanks


  [1]: https://jsfiddle.net/harshsri/93qbghgk/

【讨论】:

    【解决方案3】:

    不确定我是否理解这个问题,但此代码与您的方法类似,除了 cars 将仅基于示例数据有一项,即第三项li 在数据中。 (各种if 条件被格式化以便于查看。)

    cars = cars.reduce( ( ca, car2, ci, a ) => {
        let b = $.isArray( ca ) ? ca : [];
        a.forEach( car => {
            if (
                (
                    ( car.attr( 'data-original-price' ) && car.attr( 'data-original-price' ) === car2.attr( 'data-price' ) ) ||
                    ( car2.attr( 'data-original-price' ) && car2.attr( 'data-original-price' ) === car.attr( 'data-price' ) )
                ) &&
                ( car.attr( 'data-base-price' ) !== car2.attr( 'data-base-price' ) ) &&
                ( car.attr( 'data-price' ) !== car2.attr( 'data-price' ) ) &&
                ( car.attr( 'data-type' ) === car2.attr( 'data-type' ) ) &&
                ( car.attr( 'data-vehicle-example' ) === car2.attr( 'data-vehicle-example' ) ) &&
                ( car.attr( 'data-location-id' ) === car2.attr( 'data-location-id' ) ) &&
                ( car.attr( 'data-dropoff-location-id' ) === car2.attr( 'data-dropoff-location-id' ) )
            ) {
                if ( car.hasClass( 'listing-prepaid' ) ) {
                    car.find( '.column-price' )
                        .addClass( 'prepaid-match' )
                        .append( car2.find( '.column-price div.retail' ) )
                        .find( 'div.retail:not(.prepaid) p.button a' )
                            .text( 'Pay Later' );
    
                    b.push( car );
                }
            }
        } );
        return b;
    } );
    

    【讨论】:

      【解决方案4】:

      我会以完全不同的方式处理这个问题。为了帮助您入门,以下解决方案应该让您走上正确的道路。根据提供的数据集,它还应该满足您的所有(或大部分)要求。

      const carsUniq = new Map()
      
      cars.forEach($car => {
        const cKeys = $car.data()
        const carAttrsId = [    
          cKeys.dropoffLocationId,
          cKeys.locationId,
          cKeys.type,
          cKeys.vehicleExample
        ].join('')
      
        const sCar = carsUniq.get(carAttrsId)
        if (!sCar) {
          carsUniq.set( carAttrsId, cKeys )
        } else {
          for(const c in sCar) {
            if ( !sCar[c] && cKeys[c] ) sCar[c] = cKeys[c]
          }
        }
      })
      

      --

      它是如何工作的?

      1. 创建用于跟踪汽车的地图。
      2. 通过将特定汽车道具引用到carAttrsId 来确定汽车是否是重复的。 [O(1) 查找]
      3. 如果在地图中找到一辆车,它一定是重复的,因此我们将数据集组合成一个标准化对象。
      4. 最终结果是carsUniq.values() 是一个数组like 对象,包含独特的汽车。

      --

      根据您的数据集 carsUniq包含 3 辆独特的汽车

      "SX-34.0910834--118.352194SX-34.0910834--118.352194ICARChevrolet Cruze" => {…}
      "ZR-34.1958--118.3489ZR-34.1958--118.3489IDARToyota Corolla" => {…}
      "FX-34.0629025--117.6140867FX-34.0629025--117.6140867SCAR" => {…}
      

      --

      更新 - 改进了以前的代码并添加了根据要求将项目转换为 li 元素的功能。

      const carsUniq = new Map()
      
      cars.forEach($car => {
        const cKeys = $car.data()
        const { dropoffLocationId, locationId, type, vehicleExample } = cKeys
        const carAttrsId = dropoffLocationId + locationId + type + vehicleExample;
      
        const sCar = carsUniq.get(carAttrsId)
        if (!sCar) {
          carsUniq.set( carAttrsId, cKeys )
        } else {
          for(const c in sCar) {
            if ( !sCar[c] && cKeys[c] ) sCar[c] = cKeys[c]
          }
        }
      })
      
      const dasherizedCarKeys = new Map()
      const dasherizedData = str => {
        const k = dasherizedCarKeys.get(str)
        if (!k) {
          dasherizedCarKeys.set(str, 
             'data-' + str.replace(/([a-zA-Z])(?=[A-Z])/g, '$1-').toLowerCase())
        }
        return k
      }
      
      carsUniq.forEach(car => {
        const tCar = {}
        const carKeys = Object.keys(car).map(dasherizedData)
        for (const c in car) {
          tCar[dasherizedCarKeys.get(c)] = car[c]
        }
        $('<li>').attr(tCar).appendTo("#output")
      })
      

      输出:

      <li data-vehicle-example="Chevrolet Cruze" data-original-price="180.15" data-price="180.15" data-type="ICAR" data-dropoff-location-id="SX-34.0910834--118.352194" data-location-id="SX-34.0910834--118.352194"></li>
      <li data-vehicle-example="Toyota Corolla" data-price="301.43" data-type="IDAR" data-dropoff-location-id="ZR-34.1958--118.3489" data-location-id="ZR-34.1958--118.3489"></li>
      <li data-price="198.81" data-type="SCAR" data-partner-code="FX" data-dropoff-location-id="FX-34.0629025--117.6140867" data-location-id="FX-34.0629025--117.6140867"></li>
      

      【讨论】:

      • 嗨,Fabb!感谢您的帖子 :) 我现在正在运行代码...我非常喜欢这种方法,我该如何编辑它以返回实际的
      • html 而不是数组中的对象信息?
    • 您将从模板库中创建li 元素,即在前端,例如 Angular、React、Vue 等...这超出了本问题的范围。跨度>
    • 嗯,我喜欢这有多快。但是,我的主要目标是将来自每个匹配元素的信息组合到一个列表中,同时修改现有的汽车数组。你能修改你的答案吗?抱歉,如果不清楚。
    • 是的,您只需像这样重新分配它:cars = [ ...carsUniq.values() ];
    • 您的最新更新显示了完全不同的汽车阵列。你到底遇到了什么问题?如果无法复制您的确切环境,我无法为您提供准确的工作代码。我提供的代码仍然可以用来解决您的问题。如果您想要准确的工作代码符合您的规范,您应该创建一个 codepen 或 jsbin 来复制。赞成并接受任何有帮助的解决方案也是有礼貌的。最后,StackOverflow 旨在帮助指导您,而不是为您完成工作。如果您在帮助下无法解决问题,您可能需要聘请能够解决问题的人。
    • 猜你喜欢
      相关资源
      最近更新 更多
      热门标签