js——数据操作——实现阶梯价格排序——基础积累

news2024/11/19 1:18:30

最近在写网络报价的时候,遇到一个需求,就是要根据采购数量,找到符合数量的阶梯区间,并找到最便宜的采购价格。

比如下面:

let originViewList = [
	{
		id:1,
		incrementalQuantity:10,
		priceList:[
			{
				minQuantity:1,
				price:20
			},
			{
				minQuantity:1,
				price:18
			},
			{
				minQuantity:300,
				price:17
			}
		]
	}
]

上面数据中的incrementalQuantity是增长量,minQuantity是阶梯数,比如采购的数量是200,则可以选择minQuantity为1的,然后增长量是10的,这样,200 = 1+1020;则最后的采购量是201。如果选择minQuantity为300,则最低采购量只能是300了。两者价格比较:20120与300*17相比较,还是选择minQuantity为1的采购价格更低,而且minQuantity为1的价格为18的采购价更低,所以最后选择的是{minQuantity:1,price:18}的一组。

所以要实现的效果:

1.根据阶梯数+增长量:获取最终的采购量,阶梯数低于采购量的,需要配合增长量。阶梯数高于采购量的,直接使用阶梯数作为采购量
2.如果阶梯数有相同的,则需要找个价格最低的

下面是我的解决思路:

解决步骤1:根据采购量找到介于哪两个阶梯价之间

findNearestNumber(arr, target){
    return arr.reduce((pre, curr) => {
        return Math.abs(pre - target) > Math.abs(curr - target) ? curr : pre;
    })
},

使用方法:

let numArr = [1,1,20,30];
let num = 12;
let nearNum = this.findNearestNumber(numArr, num);
let nearIndex = numArr.indexOf(nearNum);
if (numArr[nearIndex] > num) {
    nearIndex = nearIndex - 1 > -1 ? nearIndex - 1 : 0;
}
console.log(nearIndex);

在这里插入图片描述
也就是说12最接近的索引是1,也就是介于索引1到索引2之间。
在这里插入图片描述
再看下数量是2的,最接近的索引是0,索引1也是最接近的,这种相同阶梯数的后面有处理。

解决步骤2:根据阶梯数+增长量获取最终的采购量

let arr = originViewList[0].priceList;
let resultNum = Math.ceil((num - arr[nearIndex].minQuantity) / this.originViewList[index].incrementalQuantity) * this.originViewList[index].incrementalQuantity + arr[nearIndex].minQuantity;
console.log('numArr', numArr, nearIndex, resultNum);

上面数据中的incrementalQuantity是增长量,minQuantity是阶梯数,比如采购的数量是200,则可以选择minQuantity为1的,然后增长量是10的,这样,200 = 1+10*20;则最后的采购量是201。如果选择minQuantity为300,则最低采购量只能是300了。

解决步骤3:如果阶梯数有相同,则需要根据价格排序,找最低价的

//如果有数量相同的情况
let eqIndexArr = [];
numArr.forEach((n, nIndex) => {
    if (n == numArr[nearIndex]) {
        eqIndexArr.push(nIndex);
    }
})
if (eqIndexArr.length > 1) {
    let eqPriceArr = [];
    eqIndexArr.forEach((eq) => {
        eqPriceArr.push({ index: eq, price: arr[eq].price });
    })
    const sortBy = (field) => {
        return function (a, b) {
            return a[field] - b[field];
        };
    }
    let maxArr = eqPriceArr.sort(sortBy('price'));//对象数组根据price价格字段升序排列
    this.OptimalIndex[index] = maxArr[0].index;
    res = resultNum * maxArr[0].price;//采购量*最低价格
}

解决步骤4:如果没有相同阶梯价的,则直接计算

//当前阶梯价*采购量与下一个的最小数量*价格相比较,谁的采购价低,选择谁
if (resultNum * arr[nearIndex].price < arr[nearIndex + 1].minQuantity * arr[nearIndex + 1].price) {
    this.OptimalIndex[index] = nearIndex;
    res = resultNum * arr[nearIndex].price;
} else {
    this.OptimalIndex[index] = nearIndex + 1;
    res = arr[nearIndex + 1].minQuantity * arr[nearIndex + 1].price;
}

上面的两种情况都能拿到最终的采购总价了。下面根据采购总价进行排序:

//sortLevel  是升序还是降序的判断
priceSort(num) {
    var _that = this;
    this.viewList.forEach((item, index) => item.Index = index);
    this.originViewList = JSON.parse(JSON.stringify(this.viewList));
    if (this.viewList.length == 1) {
        _that.findPriceListPrice(this.viewList[0].priceList, num, this.viewList[0].Index);
    } else {
        this.viewList.sort(function (a, b) {
            //找index  a.priceList   b.priceList
            var aPrice = _that.findPriceListPrice(a.priceList, num, a.Index);
            var bPrice = _that.findPriceListPrice(b.priceList, num, b.Index);
            return !_that.sortLevel ? (aPrice - bPrice) : (bPrice - aPrice);
        })
    }
},

合并代码记录:
最终代码记录:

priceSort(num) {
    var _that = this;
    this.viewList.forEach((item, index) => item.Index = index);
    this.originViewList = JSON.parse(JSON.stringify(this.viewList));
    if (this.viewList.length == 1) {
        _that.findPriceListPrice(this.viewList[0].priceList, num, this.viewList[0].Index);
    } else {
        this.viewList.sort(function (a, b) {
            //找index  a.priceList   b.priceList
            var aPrice = _that.findPriceListPrice(a.priceList, num, a.Index);
            var bPrice = _that.findPriceListPrice(b.priceList, num, b.Index);
            return !_that.sortLevel ? (aPrice - bPrice) : (bPrice - aPrice);
        })
    }
},
findPriceListPrice(arr, num, index) {
   var res = 99999999;
   let numArr = arr.map(a => a.minQuantity);
   if (!num) {
       res = 99999999;
   } else {
       let nearNum = this.findNearestNumber(numArr, num);
       let nearIndex = numArr.indexOf(nearNum);
       if (numArr[nearIndex] > num) {
           nearIndex = nearIndex - 1 > -1 ? nearIndex - 1 : 0;
       }
       let resultNum = Math.ceil((num - arr[nearIndex].minQuantity) / this.originViewList[index].incrementalQuantity) * this.originViewList[index].incrementalQuantity + arr[nearIndex].minQuantity;
       console.log('numArr', numArr, nearIndex, resultNum);
       if (nearIndex < arr.length - 1) {
           //如果有数量相同的情况
           let eqIndexArr = [];
           numArr.forEach((n, nIndex) => {
               if (n == numArr[nearIndex]) {
                   eqIndexArr.push(nIndex);
               }
           })
           if (eqIndexArr.length > 1) {
               let eqPriceArr = [];
               eqIndexArr.forEach((eq) => {
                   eqPriceArr.push({ index: eq, price: arr[eq].price });
               })
               const sortBy = (field) => {
                   return function (a, b) {
                       return a[field] - b[field];
                   };
               }
               let maxArr = eqPriceArr.sort(sortBy('price'));
               this.OptimalIndex[index] = maxArr[0].index;
               res = resultNum * maxArr[0].price;
           } else {
               if (resultNum * arr[nearIndex].price < arr[nearIndex + 1].minQuantity * arr[nearIndex + 1].price) {
                   this.OptimalIndex[index] = nearIndex;
                   res = resultNum * arr[nearIndex].price;
               } else {
                   this.OptimalIndex[index] = nearIndex + 1;
                   res = arr[nearIndex + 1].minQuantity * arr[nearIndex + 1].price;
               }
           }
       } else {
           this.OptimalIndex[index] = nearIndex;
           res = resultNum * arr[nearIndex].price;
       }
   }
   return res;
},
findNearestNumber(arr, target){
   return arr.reduce((pre, curr) => {
       return Math.abs(pre - target) > Math.abs(curr - target) ? curr : pre;
   })
},

上面的代码逻辑其实是有问题的,最正确的解决办法就是:根据每一个的阶梯数,获取最终的采购量,然后与各自的价格相乘,找最低的作为最终的采购价。

这样才是最正确的。

下面附上最正确的解决办法:

findPriceListPrice(list, num, index) {
  var res = 99999999;
  let arr = JSON.parse(JSON.stringify(list));
  arr && arr.forEach((a, aIndex) => {
      a.index = aIndex;
  })
  console.log('arr', arr);
  if (!num) {
      res = 99999999;
  } else {
      arr && arr.forEach(item => {
          if (item.minQuantity < num) {
              item.resultNum = Math.ceil((num - item.minQuantity) / this.originViewList[index].incrementalQuantity) * this.originViewList[index].incrementalQuantity + item.minQuantity;
          } else {
              item.resultNum = item.minQuantity;
          }
          item.totalPrice = item.resultNum * item.price;
      })
      const sortBy = (field) => {
          return function (a, b) {
              return a[field] - b[field];
          };
      }
      let maxArr = arr.sort(sortBy('totalPrice'));
      console.log('maxArr', maxArr);
      this.OptimalIndex[index] = maxArr[0].index;
      res = maxArr[0].totalPrice;
  }
  return res;
},

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1683588.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

加速短剧出海,优秀出海产品技术服务金帆奖颁布

当碎片化内容消费成为主流&#xff0c;短剧凭借其短小精悍、环环相扣、高频爆点等优势迅速拿捏大众喜好。作为泛娱乐市场又一个新兴的亮点&#xff0c;不止国内&#xff0c;伴随着碎片娱乐的海外移动观剧习惯持续培养&#xff0c;短剧供给量与消费规模不断上升&#xff0c;海外…

使用DockerFile 编写 指令来构建镜像

文章目录 前言使用DockerFile 编写 指令来构建镜像1. 构建2. 验证 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话&#x…

【课后练习分享】Java用户注册界面设计和求三角形面积的图形界面程序

目录 java编程题&#xff08;每日一练&#xff09;&#xff1a; 问题一的答案代码如下&#xff1a; 问题一的运行截图如下&#xff1a; 问题二的答案代码如下&#xff1a; 问题二的运行截图如下&#xff1a; java编程题&#xff08;每日一练&#xff09;&#xff1a; 1.…

内存马实战(持续更新中)

注&#xff1a;这篇文章记录在我的语雀里面&#xff0c;语雀格式好看一点&#xff0c;地址&#xff1a; https://ganmaocai.yuque.com/ghgp8x/zoy1yn/faet35ae9gpxzn61 计划 复现以下框架的内存马注入&#xff1a; shiro&#xff1a; 普通内存马 冰蝎马 WebSocket马 xxl-job…

【Linux】-Elasticsearch安装部署[16]

目录 简介 安装 1、添加yum仓库 2、安装es 3、配置es 4、启动es 5、关闭防火墙 6、测试 简介 全文搜索属于最常见的要求&#xff0c;开源的Elasticsearch&#xff08;以下简称es&#xff09;是目前全文搜索引擎的首选。它可以快速的储存、搜索和分析海量数据。维基百科…

蓝牙模块七种工作模式——蓝牙Mesh组网工作模式

蓝牙Mesh组网模块技术在2017年得到SIG批准&#xff0c;这是一种独立的网络技术&#xff0c;兼容4及5系列蓝牙协议。它把蓝牙设备作为信号中继站&#xff0c;利用低功耗蓝牙广播的方式进行信息收发&#xff0c;蓝牙Mesh组网技术拓展了蓝牙的通讯关系&#xff0c;打破了以往蓝牙设…

Vue3 ts实现将assets中的图片转为file格式,实现本地图片选择上传功能

Vue3 ts实现将assets中的图片转为file格式&#xff0c;实现本地图片选择上传功能 1、需求描述2、关键代码3、img标签src使用变量打包后图片无法展示 1、需求描述 用户可以选项系统固定的几个图标&#xff0c;也可以自定义上传图片。系统固定图标存在 src\assets\images\app 路径…

6款网页表白代码6(附带源码)

6款网页表白代码6 前言效果图及部分源码1.爱心倒计时2.一起看星星3.爱心4.爱心&#xff08;有鼠标移动特效&#xff09;5.爱心&#xff08;高级效果&#xff09;6.爱心&#xff08;3D效果&#xff09; 领取源码下期更新预报 前言 大部分人都有喜欢的人&#xff0c;学会这些表白…

综述 | 走向图对比学习:综述与展望

【摘要】近年来&#xff0c;图的深度学习在各个领域取得了显著的成功。然而&#xff0c;对带注释的图形数据的依赖仍然是一个很大的瓶颈&#xff0c;因为它的成本过高且耗费时间。为了应对这一挑战&#xff0c;图的自监督学习(SSL)得到了越来越多的关注&#xff0c;并取得了重大…

hubilder Android模拟器华为手机连接不上

APP真机测试注意点&#xff1a; 1. 同一个局域网下 2. 手机连接USB模式&#xff08;华为选择USB配置&#xff1a;音频来源&#xff09; &#xff0c;开发者模式 3. 实在不行重启HBuilderX再运行真机 可是卡在了“正在安装手机端HBuilder调试基座...” 就没反应了&#xff1f;&…

rust的版本问题,安装问题,下载问题

rust的版本、安装、下载问题 rust版本问题&#xff0c; 在使用rust的时候&#xff0c;应用rust的包&#xff0c;有时候包的使用和rust版本有关系。 error: failed to run custom build command for pear_codegen v0.1.2 Caused by: process didnt exit successfully: D:\rus…

功耗相关总结

文章目录 功耗相关的使用场景MCU中低功耗的应用RTOS中低功耗应用 功耗相关的使用场景 目前越来越多的嵌入式设备采用电池进行供电&#xff0c;而不是跟台式电脑一样&#xff0c;可以一直连接着电源。在电池供电的场景下&#xff0c;对功耗的要求很高&#xff0c;工程师们尽量希…

查看当前Shell系统环境变量

查看当前Shell系统环境变量 查看命令 env效果 查看Shell变量(系统环境变量自定义变量函数) 命令 set效果 常用系统环境变量 变量名称含义PATH与windows环境变量PATH功能一样&#xff0c;设置命令的搜索路径&#xff0c;以冒号为分割HOME当前用户主目录&#xff1a;/rootSH…

uniapp中使用 iconfont字体

下载 iconfont 字体文件 打开 iconfont.css 文件&#xff0c;修改一下 把文件 复制到 static/iconfont/… 目录下 在App.vue中引入iconfont 5. 使用iconfont 使用 iconfont 有两种方式&#xff0c; 一种是 class 方式&#xff0c; 一种是使用 unicode 的方式 5.1 使用 class 的…

DNS域名解析与智能选路

要开始访问公网了&#xff01;&#xff01; 你在访问百度的时候&#xff0c;你也不知道百度的IP地址是啥&#xff0c;你只知道他的域名是baidu AD这台设备可以做入站的负载平衡&#xff0c;AD来选择你访问的时候是用联通网还是电信网&#xff0c;避免卡顿 pc并不会域名解析&…

在aspNetCore中 使用System.Text.Json的定制功能, 将定制化的json返回给前端

C# 默认大写, 而大部分的前端默认小写, 这时候可以如此配置: builder.Services.AddControllers().AddJsonOptions((opt) > {opt.JsonSerializerOptions.PropertyNamingPolicy System.Text.Json.JsonNamingPolicy.CamelCase;opt.JsonSerializerOptions.WriteIndented true…

案例 | 澳鹏自动驾驶标注方案入选虎嗅智库行业报告

随着自动驾驶技术发展及方案演进&#xff0c;市场对于数据标注的数量和质量的需求都呈现指数级增长。传统的手工标注已不能满足标注需求&#xff0c;自动标注伴随大模型的发展应运而生。 在这一背景下&#xff0c;虎嗅智库发布《自动驾驶数据标注技术落地洞察》&#xff0c;并…

PHP在线制作表白网源码

PHP在线制作表白网源码&#xff0c;送女友个惊喜吧&#xff0c;无数据库&#xff0c;上传就能用&#xff0c;后台/admin&#xff0c;账号密码都是admin 百度网盘&#xff1a;https://pan.baidu.com/s/1rbD2_8IsP9UPLK-cdgEXfA?pwdre59

【Qt 学习笔记】Qt常用控件 | 布局管理器 | 空白项Spacer

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 布局管理器 | 添加空白Spacer 文章编号&#xff1a;Qt 学…

欢聚笔试题求助帖

事情是这样的&#xff0c;这段时间一直在求职投简历&#xff0c;期望在暑假之前接到一份大数据开发的实习工作。投了很多公司&#xff0c;然后就收到了欢聚的笔试邀约&#xff0c;HR说要我一天之内做出来&#xff0c;恰巧第二天还有组会要汇报&#xff0c;我就先放下了&#xf…