更新:
我有一个名为 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.
要求
汽车数组:
<li xmlns="www.w3/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 & 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="www.w3/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 & 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="www.w3/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="www.w3/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在 developer.mozilla/en-US/docs/Learn/HTML/Howto/Use_data_attributes
一般来源: developer.mozilla/en -US / docs / Web / API / HTMLElement , developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
更多推荐
匹配数组中的对象并进行合并
发布评论