项目链接:https://gitee.com/xyjtysk/quotationTools

采用什么样的数据结构

那么我们希望读出来的数据是这个什么样子呢?也就是数据结构是怎么样的?

既然Excel是个二维表格,那么读出来的数也放在一个二维表格里面得了。

我们一个简化版的例子来看,下面的表格是从原始表格中截出来的一部分。

产品编码 产品型号 数量 标准价(RMB)
0235A0W2 RT-MSR5660 2 50000

这样的缺点在于:取每个元素,需要计算index,不方便编程。

比如我们要取第三行的“RT-MSR5660”,我们需要使用a[1][1]来取,非常不方便。

我们知道最方便取的数据结构为dict,只要传进去一个key,它就会返回一个value,这样的好处是

  • 可以为每一列赋予实际的含义,比如说可以把产品型号的key设为BOM,我们要取“RT-MSR5660”的时候,就可以用a[1]['BOM']

  • 如果要调换列的顺序,可以轻松做到,更为的灵活

    因为每一列赋予了实际的含义,我们根本不用担心具体的顺序

那么具体的数据格式应该是怎么样的呢?

首先我们为所能用到的列分配一个key值,映射表格如下:

NHCT中的列 key值
ID ID
产品编码 BOM
产品型号 typeID
项目名称 description
单套数量 quantity
目录价 unitsNetListPrice
折扣 discount
单价 unitsNetPrice
总价 totalPrice
总目录价 totalListPrice
产线 PL
WATSON_LINE_ITEM_ID waston
备注 remarks

那么下面表格所对应的数据结构可以设计成这个样子。

产品编码 产品型号 数量 标准价(RMB)
0235A0W2 RT-MSR5660 2 50000
[
{"BOM":"产品编码",
"typeID":"产品型号",
"description":"项目名称",
"totalQuantity":"数量",
"unitsNetListPrice":"标准价(RMB)"},{"BOM":"0235A0W2",
"typeID":"RT-MSR5660",
"description":"H3C MSR 56-60路由器机框",
"totalQuantity":"2",
"unitsNetListPrice":"50000"}
]

我们来看一下特点:

  • 原始表格中的每一行转换为一个dict

  • 然后把所有行组成一个list

从Excel中读数据

既然现在数据结构已经设计好了,我们就来看如何读数据,并形成这样的数据结构吧。

首先引入模块

import xlrd

然后定义一个操作类,从excel中读取数据并转换的函数为getAssociativeArray,需要把Excel的完整路径传递进去,以及要读取的sheet的名称,还有就是为每列取的key值

class XlrdTool(XlsReader):# 作用:获取关联数组# inputHeaderKey:数组每一列的对应的键值# 返回:一个数组,数组的每一行为一个dict,代表原来表格里面的每一行,其中此dict的键名为输入的inputHeaderKey,键值为读入的excel文件的对应值。def getAssociativeArray (self, excelPathName, sheetName , inputHeaderKey):list = []try:sheetList = xlrd.open_workbook(excelPathName).sheet_by_name(sheetName);# row:表示从当前sheet读出了的每一行,# 将每一行的row_values与inputHeaderKey组成dictlist = [dict (zip (inputHeaderKey , sheetList.row_values(row))) for row in range(sheetList.nrows)];except Exception as data:print("打开文件失败,%s" % data);return list;

里面最关键的代码其实只有:

list = []sheetList = xlrd.open_workbook(excelPathName).sheet_by_name(sheetName);list = [dict (zip (inputHeaderKey , sheetList.row_values(row))) for row in range(sheetList.nrows)];

我们来一一看看。

  • 从Excel中的某个sheet里面读出数据,xlrd.open_workbook(excelPathName).sheet_by_name(sheetName)

  • [dict (zip (inputHeaderKey , sheetList .row_values(row))) for row in range(sheetList.nrows)];我们可以拆解一下:

    • 这是一个列表生成式,for row in range(sheetList.nrows)表示对读出来的数组的每一行 row 进行遍历,

    对其中某一行row

    • 首先使用xlrd中的函数row_values取出每一行的值

    • inputHeaderKey表示为每一列赋予的一个key,它是一个数组。

    • 然后使用zip把读出来的每一行与inputHeaderKey组成键值对,再在外面迁套dict形成一个字典。
      也就是
    {"BOM":"0235A0W2",
    "typeID":"RT-MSR5660",
    "description":"H3C MSR 56-60路由器机框",
    "totalQuantity":"2",
    "unitsNetListPrice":"50000"}
  • 所有的dict形成一个列表

总结一下就是,把为每列分配的key值数组与每一行进行zip,然后转换为dict,最后把所有的dict组成一个list。

数据结构的特点

上面讲了如何从Excel读取数据形成数组。

我们再来看一下这种数据结构

a = [
{"BOM":"产品编码",
"typeID":"产品型号",
"description":"项目名称",
"totalQuantity":"数量",
"unitsNetListPrice":"标准价(RMB)"},{"BOM":"0235A0W2",
"typeID":"RT-MSR5660",
"description":"H3C MSR 56-60路由器机框",
"totalQuantity":"2",
"unitsNetListPrice":"50000"}
]

它是一个嵌套的数据结构,总体上是一个list,它有两个元素,每个元素都是一个dict

那么这个地方就有个坑点了

如果我们再把这个list赋给b,然后在b中把price的价格修改了。

那么list最开始指向的dict并没有变,没有指向另一个元素,所以list没有改变,

但是dict发生改变了。

也就是a对应的那个price也发生了改变了。

所以我们需要注意,如果把list赋给另一个变量以后,一定要深复制一份。

如何遍历

对于我们这个项目来说,遍历可能是最重要的算法了。首先我们来看一下我们官方给出来的表格吧。

一套配置清单其实有若干套设备构成,每套设备又有一个子标题以及相应的详细配置信息等,还有小计等。

多套设备组成了整个清单,

在讲遍历前,我们需要对每个区域取个名字。

加上colorTag

我们可以把所有行分为如下几类:

  • header:表示总的标题

  • site:表示每一套设备的子标题

  • subtotal:对每一套设备的小计

  • total:总计

  • general:详细配置信息

这几种他们对应的颜色也可以设为不同的,所以统称为colorTag

那么怎么在程序中区分不同的行的类型呢?

我们知道之前设计的数据结构本质就是一个list,而每一行是一个dict,所以只需要再加一个键值对即可,比如总计行就加上"colorTag":"total"即可。

之前读取Excel数据的时候并没有加上这个ColorTag,那么现在要加的话,需要对整个list进行一次遍历,识别每一行的特征,加上相应的colorTag

aDiff = [i for i in ['BOM','typeID','description']  if i in self.lists[0].keys()];
colTag = aDiff[0];
for aList in self.lists:if aList[colTag] == "小计":aList['colorTag'] = "subtotal";elif aList[colTag] == "总计":aList['colorTag'] = "total";elif aList['ID'] != "":aList['colorTag'] = 'site';else:aList['colorTag'] = "general";self.lists[0]['colorTag'] = "header"

解释一下代码:

  • 首先colTag指的是'BOM','typeID','description'这几个谁存在,则取谁为colTag

  • 然后遍历数组的每一行,如果aList[colTag]="小计"或者踪迹的时候,就可以判断出是小计行或者总计行

  • 另外我们观察得到ID列除了子标题site对应的行有值,其他的行都是空的,所以可以使用aList['ID'] != ""来判断哪些是site行

  • 第一行就是header行

  • 剩下的自然是general

我们还可以再遍历一次新生成的list,然后把colorTag为site的那些行的序号取出来,这就可以确定每一套设备的起始和截止的位置了。

转载于:https://www.cnblogs.com/dy2903/p/8466604.html

【QuotationTool】主要数据结构相关推荐

  1. 数据结构(08)— 线性单链表基本操作

    1. 线性单链表数据结构 // 假定每个结点的类型用 SNode 表示 typedef struct SNodeTag {int data; // 所存储的数据元素SNodeTag *next; // ...

  2. 数据结构(06)— 线性循环链表实战

    1. 循环链表定义 单链的循环链表结点的存储结构和单链表的存储结构一样, 所不同的是: 最后一个结点的 next 域指向头结点, 而不是"空".这样, 由表尾很容易找到表头. 但若 ...

  3. 数据结构(05)— 线性单链表实战

    1. 设计思路 本项目的实质是完成对考生信息的建立.查找.插入.修改.删除等功能,可以首先定义项目的数据结构,然后将每个功能写成一个函数来完成对数据的操作,最后完成主函数以验证各个函数功能并得出运行结 ...

  4. 数据结构(04)— 线性顺序表实战

    1. 设计思路 本实战的实质是完成对学生成绩信息的建立.查找.插入.修改.删除等功能,可以首先定义项目的数据结构,然后将每个功能写成一个函数来完成对数据的操作,最后完成主函数以验证各个函数功能并得出运 ...

  5. 数据结构(03)— 数据处理基本操作(数据的查找、新增、删除、修改)

    我们先来看一个关于查找的例子.查找,就是从复杂的数据结构中,找到满足某个条件的元素.通常可从以下两个方面来对数据进行查找操作:​ 根据元素的位置或索引来查找: 根据元素的数值特征来查找. 针对上述两种 ...

  6. 数据结构(02)— 时间复杂度与空间复杂度转换

    1. 时间复杂度转化为空间复杂度 常用的降低时间复杂度的方法有递归.二分法.排序算法.动态规划等,降低空间复杂度的核心思路就是,能用低复杂度的数据结构能解决问题,就千万不要用高复杂度的数据结构. ​ ...

  7. OpenCV 笔记(09)— 常用的数据结构和函数(Vec、Point、Scalar、Size、Rect、cvtColor)

    1. Vec 对象类型 Vec 是一个主要用于数值向量的模板类.我们可以定义向量的类型和组件的数量: Vec<double, 19> myVector 我们还可以使用任何的预定义类型: t ...

  8. 数据结构与算法——线性结构——线性表及其表示

    -"一,线性结构 1.顺序储存结构直接表示 多项式. 1).使用数组来表示多项式.(用数组下标来表示指数,值来表示系数) 可以表示成: 2).使用结构数组来表示.(把系数和指数看成一个二元组 ...

  9. 队列:实用程序服务和数据结构

    队列:实用程序服务和数据结构 Queues: utility services and data structures 队列实用程序服务 Nucleus RTOS有四个API调用,它们提供与队列相关的 ...

最新文章

  1. Algorithm之MC:Monte Carlo method蒙特·卡罗方法的简介、实现、应用
  2. 地图画指定区域_零基础学CAD绘制一张桌子为例,使亲们更好地熟悉三维绘图环境...
  3. [当人工智能遇上安全] 7.基于机器学习的安全数据集总结
  4. 越过 __chkesp 检测的缓冲区溢出
  5. Ocean的礼物(线段树单点修改)
  6. linux之more命令
  7. 新年寄语 | 2018 以及 Oracle 18c 一个时代的开启
  8. win10玩cf不能全屏_游戏莫名卡顿三招搞定!Win10游戏优化教程
  9. 计算机硬件系统的安全,维护硬件系统的计算机安全论文
  10. Android PdfViewer
  11. kmp算法next计算方法_【数据结构——串】KMP算法——next数组Python的实现方式
  12. 烈火如歌手游找回服务器,《烈火如歌》05月02日新服公告:侠肝义胆
  13. Edraw Max 9.4中文版激活教程
  14. 计算机主板设置中的英语,技嘉主板bios设置教程,技嘉主板bios中英文对照表
  15. 1330_硬件测试中的BCI测试
  16. 自动化运维—ansible
  17. MCS-51单片机内部结构——CPU结构 单片机原理学习笔记(二)
  18. java.lang.NullPointterException:
  19. netty案例,netty4.1中级拓展篇五《基于Netty搭建WebSocket,模仿微信聊天页面》
  20. 【LLYD】That 70s show: why the disco decade is back in fashion

热门文章

  1. 如何将网站数据导入服务器里,网站是无意识的将数据导入和导出Web客户端
  2. 笔记本老出现计算机,电脑老是自动重启,教您如何有效解决这个问题
  3. 【linux】查看字体
  4. ab不同时为0c语言程序表达式,2016年暨南大学信息科学技术学院C语言程序设计复试笔试最后押题五套卷...
  5. rust灯灭了怎么办_Rust Rc 方法整理
  6. java clone方法_java安全编码指南之:方法编写指南
  7. 梦幻手游最新服务器,梦幻西游手游12月18日新服务器开服公告
  8. 人事软件测试自学,自学软件测试什么课程
  9. unity update 协程_Unity协程,停止协程及yield return使用_019
  10. python微信加人_Python帮你微信头像任意添加装饰,别再@微信官方了_编程语言_python考试视频_python教程_课课家...