【QuotationTool】主要数据结构

项目链接: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


    image.png

从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组成dict
            list = [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。

image.png

数据结构的特点

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

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

a = [
{"BOM":"产品编码",    
"typeID":"产品型号",    
"description":"项目名称",    
"totalQuantity":"数量",    
"unitsNetListPrice":"标准价(RMB)"},

{"BOM":"0235A0W2",    
"typeID":"RT-MSR5660",   
"description":"H3C MSR 56-60路由器机框",   
"totalQuantity":"2",    
"unitsNetListPrice":"50000"}
]

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

image.png

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

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

image.png

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

但是dict发生改变了。

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

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

image.png

如何遍历

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

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

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

image.png

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

加上colorTag

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

  • header:表示总的标题

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

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

  • total:总计

  • general:详细配置信息

image.png

这几种他们对应的颜色也可以设为不同的,所以统称为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的那些行的序号取出来,这就可以确定每一套设备的起始和截止的位置了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容