[TOC]

目标

现有字典列表

# A = [ {dict1}, {dict2} ] B = [ {dict3}, {dict2} ] C = [ {dict3}, {dict4} ] M = [A,B,C] X = []

将M去重后的字典放入列表X中,得到X = [{dict1}, {dict2},{dict3}, {dict4}]

难点字典列表

大家可能一开始会想到使用set()函数转化为集合,自动去重。但是集合是使用hash来计算并去重的,但是字典类型无法使用Hash计算。虽然可以使用类class或者命名元组namedtupe来替换字典,但是这次的场景是无法变更列表的产生源的。

列表无集合操作的方法

列表之间无法使用交并差(&,|,-)的方式的集合计算方法

思路

# json,性能差data = set([json.dumps(d) for d in data])data = [json.loads(d) for d in data]# 这种方式只能对ABC生效,对M还需要再一次循环,玛法sortedlist = []for item in listwhichneedssorting: if item not in sortedlist: sortedlist.append(item)# 这种缩短了两行for i in M: X.extend(filter(lamda s: s not in X, i)) # 使用extend()而不是append(),因为我们需要拼接的是字典列表,而不是列表的列表# lamda s: s not in X, M 匿名函数,对i中的元素是否在X中进行判断# filter() 对上面匿名函数中不满足条件(即重复的字典)进行过滤,返回尚未添加到X中的字典元素列表# 使用extend()进行追加到X中应用

主要是从neo4j中取出关系数据,分离节点,连接的关系,并转换为前端适用的数据返回

def get_nodes_relationships(graph_list=None, ret_format=None): """ 将将关系与节点分离到各自的列表中 :param graph_list: :param ret_format: :return: """ node_list = [] relationship_list = [] for i in map(lambda x: x.get('graph', None).get('nodes'), graph_list): node_list.extend(filter(lambda x: x not in node_list, i)) for m in map(lambda y: y.get('graph', None).get('relationships', None), graph_list): relationship_list.extend(filter(lambda x: x not in relationship_list, m)) # i和m都是由字典组成的列表,i为单字典列表,m为多字典列表, # 前端要求去重,这里使用函数式语句返回没有在结果列表中出现的字典,然后使用extend()追加 # 如果是面向d3,需要更改部分信息为d3适配 if ret_format == 'd3': def to_d3(link): """ 面向d3框架更改关系的键名,增加节点的数字类型 :param link: 关系 :return: 更改后返回 """ # 使用推出键值对,重新推入的方式实现变更键名为前端可以识别的source link.update(source=link.pop('startNode')) # 使用推出键值对,重新推入的方式实现变更键名为前端可以识别的target link.update(target=link.pop('endNode')) value_map = { "meta_in": 1, "slave_of": 2, "shard_to": 3 } link['value'] = value_map[link['type']] return link relationship_list = map(lambda x: to_d3(x), relationship_list) # 如果是面向echarts,需要更改部分信息为echarts适配 if ret_format == 'echarts': def to_echarts(node=None, link=None): """ echarts适配 :param node: 单个节点 :param link: 单个关系 :return: 更改后的节点或者关系 """ if (node and link) or (node is None and link is None): print("fuck you") exit(1) if node: node['name'] = node['id'] node['draggable'] = True node['category'] = node['labels'][0] del node['labels'] # del node['properties'] bom = node if link: # 使用推出键值对,重新推入的方式实现变更键名为前端可以识别的source link.update(source=link.pop('startNode')) # 使用推出键值对,重新推入的方式实现变更键名为前端可以识别的target link.update(target=link.pop('endNode')) link.update(category=link.pop('type')) del link['id'] del link['properties'] # del link['category'] bom = link return bom node_list = map(lambda node: to_echarts(node), node_list) relationship_list = map(lambda relation: to_echarts(link=relation), relationship_list) # 为什么要用set而不是list来转化map对象: # 1.去重 # 2.减小对象大小,达到缩减内存占用 # 为什么还是用list而不是set? # 1.dict对象不能被hash计算 ret = {"nodes": list(node_list), "links": list(relationship_list)} return ret