根据一个提问整理的 https://ask.csdn.net/questions/7475427 。
核心需求是,有若干集合(列表),每个集合中的元素数量是相同的:
1 2 3 4 |
[ [ "a1", "a2", "a3" ], // 可能还有 a4、a5、... [ "b1", "b2", "b3" ], [ "c1", "c2", "c3" ] // 可能还有 [ ] ... |
期望这些列表元素能如下组合
这个问题的核心是数学中的“笛卡尔积”,如果不知道这个概念解决起来确实挺费脑筋。
根据笛卡尔积的运算,只要将上面的二维数组-excel表格,以"b2"为中心,顺时针旋转90度,然后,翻个面。
生成结果如下:
1 2 3 |
[ [ "a1", "b1", "c1" ], [ "a2", "b2", "c2" ], [ "a3", "b3", "c3" ] |
然后,就可以笛卡尔积运算了。
笛卡尔乘积,又称直积,表示为X×Y,假设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。
python中 itertools包的product可以直接实现。本文做了手动实现。
下面是回答问题的完整代码,
BreakCompManager 类的 __cartesianProduct 方法实现笛卡尔积运算。
如是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
import json class TypeGroupManager: """ 分析字符串的字符类型和出现次数规则。 A为英文小写字母,B为数字,C为其它字符 """ def __getRuleKVList(self, string): """ 对字符串中的连续字符 按照 英文、数字、符号 进行计数 Args: string:字符串 Returns: list: 返回一个元素为字典的列表,字典的key是类型、value是数量。元素顺序即原字符顺序 """ typeCountList = list() # [{"A":2}, {"B":3}, {"C":1}, {"B":1}] for char in string: if char.isalpha(): # 字母 t = "A" elif char.isdigit(): # 数字 t = "B" else: # 其它字符 t = "C" count = len(typeCountList) if count > 0: last = typeCountList[count - 1] lk = list(last.keys())[0] if lk == t: num = last[lk] last[lk] = num+1 else: tv = {t:1} typeCountList.append(tv) else: tv = {t:1} typeCountList.append(tv) tmp = list() for i in typeCountList: j = json.dumps(i) tmp.append(j) return tuple(tmp) def getGroup(self, stringList): """统计给出的若干字符串的字符数量。每个字符串按照字符出现顺序判断类型,并累计出现次数。重复出现的类型新计数 Args: stringList (list): 模板字符串列表 Returns: dict: 返回一个字典「类型统计:符合规则的字符串列表」 """ groupMap = dict() # { ('{"A": 2}', '{"B": 3}', '{"C": 1}', '{"B": 1}'):['az046!1', 'ew549#0'], "B1A3C1A1":['7sas!a'] } for item in stringList: typeGroup = self.__getRuleKVList(item) group = groupMap.get(typeGroup) if group: group.append(item) else: groupMap.update({typeGroup: [item]}) # 修改值 return groupMap def __getTypeCount(self, rule): """把字典中的数字取出 ('{"A": 2}', '{"B": 3}', '{"C": 1}', '{"B": 1}') => 2311 """ cl = list() for r in rule: map = json.loads(r) k = list(map.keys())[0] num = map.get(k) cl.append(num) return cl def __splitString(self, string, cl): """根据数字对字符串拆分 ['az046!1', 'ew549#0', 'op564%4'] => [ ['az', '046', '!', '1'], ...... """ strlist = [] step = 0 for count in cl: s = string[step:count+step] strlist.append(s) step += count return strlist def breakComp(self, typeGroup): breakMap = {} for g in typeGroup: cl = self.__getTypeCount(g) strings = typeGroup.get(g) breakList = [] for s in strings: sl = self.__splitString(s, cl) breakList.append(sl) breakMap.update({g:breakList}) return breakMap class BreakCompManager: """笛卡尔积 运算 """ def __matrixTranspose(self, two_dimensional_list): ''' 原矩阵 wrap1 = ["a1", "a2", "a3"] # 包[格子cell, 格子, 格子] wrap2 = ["b1", "b2", "b3"] wrap3 = ["c1", "c2", "c3"] box = [wrap1, wrap2, wrap3] # 箱子 ''' self.box = two_dimensional_list line_count = len(self.box) # 箱子里有多少包 column_count = len(self.box[0]) # 每个包内有多少格子 # 1.1 行列转换:lambda表达式写法 # 矩阵转置。新的列数等于原来的行数;新的行数为原来的列数 # plane = [[self.box[i][j] for i in range(line_count)] for j in range(column_count)] # 1.2 直白的写法 plane = list() for c in range(column_count): # 新的二维空间。原先有多少列,这里就准备多少行 l = list() plane.append(l) for i in range(line_count): wrap = self.box[i] for j in range(column_count): colarr = plane[j] colarr.append(wrap[j]) # plane:[ # ['a1', 'b1', 'c1'], # ['a2', 'b2', 'c2'], # ['a3', 'b3', 'c3'] # ] return plane def __cartesianProduct(self, plane): # 2.1 生成 笛卡尔积/笛卡尔集:内置api直接生成 # import itertools # result = itertools.product(*plane) # for i in result: # print(i) # 2.2 lambda写法 # rows = [row for row in plane] # result = [[]] # 定义一个二维列表,内部列表暂时为空。即 len(result)为1,len(result[0])为0 # for row in rows: # result = [x+[y] for x in result for y in row] # for i in result: # print(i) # 2.3 直白写法 result = [[]] for p_line in plane: tmp = [] for r_line in result: for p_cell in p_line: tmp.append(r_line + [p_cell]) result = tmp return result def compose(self, comp_dict): result = dict() for key in comp_dict: group = comp_dict.get(key) plane = self.__matrixTranspose(group) decare = self.__cartesianProduct(plane) result.update({key : decare}) return result if "__main__" == __name__: srcList = ['az046!1', '7sas!a', '54821s', '!!', 'ew549#0', '12345p', '5qqs%$s', '67890b', 'op564%4'] tgManager = TypeGroupManager() group = tgManager.getGroup(srcList) comps = tgManager.breakComp(group) print("分组完成") bcManager = BreakCompManager() result = bcManager.compose(comps) print("重组完成") for key in result: print("{:*^10}".format('组')) value = result[key] for j in value: print(j) |
- end
声明
本文由崔维友 威格灵 cuiweiyou vigiles cuiweiyou 原创,转载请注明出处:http://www.gaohaiyan.com/2847.html
承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设