匹配数组中的对象并进行合并 [英] Matching Objects in Array and Consolidate

查看:89
本文介绍了匹配数组中的对象并进行合并的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:

我有一个名为 cars 的对象数组,其中包含li标记有关于汽车的属性数据(例如价格,汽车类型等)。我的目标是根据特定条件将这些汽车整合到一个列表中。

I have an array of objects called cars that contains li tags with attribute data about cars (such as price, car type, etc.). My goal is to consolidate these cars into one single listing if they are a match based on certain criteria.

要求


  1. 快速表现

  2. 保持相同的汽车阵列结构

  3. 主要目标:匹配预付费和零售清单 - 将零售清单中的HTML(例如按钮和定价信息)合并到预付清单中。请参阅:

  4. 如果匹配(基于IF语句中的条件),则删除匹配的列表,而不使用listing-prepaid类并使用零售清单中的某些信息更新匹配的预付款列表。

  1. Fast Performance
  2. Keep same cars array structure
  3. Main Goal: Match Prepaid and Retail listings - Combine the HTML from Retail listing (such as button and pricing information) into Prepaid Listing. See:
  4. If there is a match (based on criteria in IF statement), then remove the matched listing without class "listing-prepaid" AND update matched prepaid listing with certain information from retail listing.

汽车数组:

<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,车辆示例等)。第一个列表应该从数组中删除,因为它没有类别列表预付费,并​​且.column-price中的HTML应该添加到其预付费匹配中(在此示例中,数组中的第3个列表)。

最终产品:

代码:

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


推荐答案

正如评论中所提到的,使用reduce可以保持复杂性在 O(n)。这基本上意味着,两倍大小的列表将花费两倍的时间,因为算法只迭代汽车列表一次。

As mentioned in the comments, using reduce keeps the complexity at O(n). This basically means, that a list twice the size will take twice the time, as the algorithm only iterates the list of cars once.

如果你需要比较每个项目汽车阵列中的汽车阵列与汽车阵列中的每个其他项目相比,循环式方法的复杂性将是 O(n ^ 2),对于每个附加项目(粗略地说),将会有指数级的循环/时间使用。

If you need to compare each item in the cars array to each other item in the cars array, the complexity with loop-like approaches will ne O(n^2), as for every additional item (roughly speaking) there will be exponentially more loops/time used.

我不是100%肯定你的javascript对象的数据结构,但是下面的方法应该有效:

I'm not 100% certain about the data structure of your javascript objects, but the following approach should work:

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

   });
}, [];

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

An alternative approach would be to build a data structure that allows access to elements based on their attributes in a constant time (O(1)). An example would be a (Hash)Map. In this case for each element that the algorithm is looping over it is not required to loop through the whole list again to identify matches but to query the Map structure for matches.

奖励:鉴于 car 是HTMLElement,您可以使用 dataset 属性访问数据 - * 值更简单:

Bonus: Given that car is a HTMLElement, you may use the dataset property to access the data-* values easier with:

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 / HTMLElement https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

这篇关于匹配数组中的对象并进行合并的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆