正在将排序列表/迭代器/生成器合并为一个值流...
我需要将几个值源合并为一个值流. 全部 这些来源已经分类了,我需要从 它们都按顺序排序. 换句话说: S1 = [10,20,30,40,50] S2 = [15,25] S3 = [17,27,37] 为???(s1,s2,s3)的值: 打印值 将打印出该顺序的10、15、17、20、25、27、30、30、40、50. 来源是光标,从几个数据库中检索数据,而不是从 同一台服务器,并且有可能从 几个来源. 因此,任何将其全部加载到的方法 记忆和排序不好,因为它会太多的内存. Python中是否有能力做我想要的功能或什么? 我 已经提出了我自己的方法,但是由于它使用了发电机,所以我不是 确保有多少开销. 此外,由于值 从光标检索将是" fieldname"的字典:value 对,该方法要么需要处理该构造(并且是 告诉fieldname要排序),或者能够将函数对象带到 用于比较操作. 基本上,除非有人可以指向我,否则我会使用自己的功能 到已经可用的东西. 似乎找不到任何东西 在内置模块中,但我找不到glob.glob. 对于如何找到文件名,所以谁知道它叫什么:) 由于我需要处理可变来源列表(也就是说,二合 应用程序,另外3个,第三个中的4-5),一种简单的2源方法 还不够 为此制作包装,因为那是我所做的. - - lassevågsætherkarlsenhttp://usinglvkblog.blogspot.com/ 邮件:la ***@vkarlsen.no PGP KEYID:0x2A42A1C2
# 回答1
LasseVågsætherKarlsen写道: 我怀疑您会发现一个预建的,很容易创建自己的 毕竟. 发电机是BTW Python的相当快的结构. 这是我几分钟后搅动的东西: def prientiter(value): it = iter(value) 尝试: 返回it.next(), 除了停止,错误: 没有返回,没有 def inorder(比较, *args): 迭代器= [ [value,it] 对于(value,it),在[Args中的ARG]中的[ARG)] 如果不是 这是给予的 iterators.sort() 迭代器时: 产生迭代器[0] [0] 尝试: 值=迭代器[0] [0] =迭代器[0] [1] .next() 除了停止,错误: 迭代器.pop(0) 别的: 如果Len(迭代器)> 1和比较(值, 迭代器[1] [0])== 1: iterators.sort() 继续 如果__name__ ==" __ -main __": S1 = [10,20,30,40,50] S2 = [15,25] S3 = [17,27,37] S4 = [] 为Inorder(CMP,S1,S2,S3,S4)的值: 打印值 无论如何,玩得开心, 麦克风 - - ________________________________________________________________ 迈克·C·弗莱彻(Mike C. Fletcher) 设计师,VR水管工,编码器http://www.vrplumber.com http://blog.vrplumber.com
# 回答2
好的,那个看起来比我想出的还要嘶哑. 我从您的解决方案中学到的几件事,请纠正我 误解了一些东西: 1. Lis t包含其他列表将根据第一个元素进行排序 在里面的列表上? 2. sort(),pop()不是昂贵的操作 除此之外,您似乎不使用CMP操作员,但这很容易 固定的. 这个看起来比我的好得多,这就是我想到的: def merge_sorted(Iterables,比较= none): """ 发电机将获取迭代/发电机列表 单独分类,然后生产 通过从每个 来源每个呼叫. @param iterables:迭代/发电机列表以检索值 从 @Type Iterables:Iterables/Generators的列表 @Param比较:可选的FN(V1,V2)函数,可以比较两个 值,如果V1 (1,2) left_iterable = iterables [0] right_iterable = merge_sorted([iTerables [1],iterables [2]], 比较) 对于Merge_sorted中的值([left_iterable,right_iterable], 比较): 产量值 Elif Len(iterables)== 4: #4来源,分为(0,1)<->(2,3) left_iterable = merge_sorted([iTerables [0],iterables [1]], 比较) right_iterable = merge_sorted([iTerables [2],iterables [3]], 比较) 对于Merge_sorted中的值 比较): 产量值 Elif Len(Iterables)> 4: #> 4个来源,分为(0,1)<->(2,...) left_iterable = merge_sorted([iTerables [0],iterables [1]], 比较) right_iterable = merge_sorted(iterables [2:],比较) 对于Merge_sorted中的值 比较): 产量值 提高止动 #该方法只有只有两个来源才能到达这里, 很容易处理 i1 = iter(iterables [0]) i2 = iter(Iterables [1]) #如果可能的话,从两个来源获取前两个值 尝试: v1 = i1.next() has_v1 = true 除了停止: has_v1 = false 尝试: v2 = i2.next() has_v2 = true 除了停止: has_v2 = false #只要我们从两个生成/迭代器/erthing中获得值, 比较并产生最低的 #第二,然后从相应的源获取下一个值 而has_v1和has_v2: #解决V1和V2的哪个首先 如果比较不是没有: comp =比较(v1,v2) 如果comp <= 0: farts_v1 = true 别的: fard_v1 = false 别的: 如果V1 <= V2: farts_v1 = true 别的: fard_v1 = false #产生下一个值,然后从 Cor 响应来源 如果fard_v1: 产量V1 尝试: v1 = i1.next() 除了停止: has_v1 = false 别的: 产量v2 尝试: v2 = i2.next() 除了停止: has_v2 = false #当我们到达这里时,我们有3种可能性: #1. has_v1 == true,has_v2 == false->屈服v1/i1的其余部分和 只是退出停止异常 #2. has_v1 == false,has_v1 == true->屈服v2/i2和 只是退出停止异常 #3. has_v1 == has_v2 == false--> while-loops会跳过,功能 掉下来 而has_v1: 产量V1 v1 = i1.next() 而has_v2: 产量v2 v2 = i2.next()
# 回答3
" lassevågsætherKarlsen" 写道: 有关最有效,最优雅的解决方案,请查看Raymond Hettinger的答复:http://aspn.activestate.com/aspn/coo.../recipe/141934 乔治
# 回答4
谢谢,看起来像Mike的解决方案,除了它使用 内置HAPQ模块. 虽然该代码少于Mike的解决方案,但似乎缺乏 控制比较操作的能力,这意味着它不会 就我而言工作. 我都需要能够在任意字段上进行排序 名称(可以使用我将字段放置的列表完成的列表完成),并且 也能够以不同于最小的顺序排序. 也许通过调整通过每个源返回的数据 会这样做. 我会研究它.
# 回答5
" lassevågsætherKarlsen" 写道: 是的,内置堆不进行比较操作有点不方便,但是您 可以通过将每个项目转换为(键,项目)元组来轻松滚动自己的堆. 现在我在想 关于它,这可能是食谱的一个很好的补充. 乔治
# 回答6
LasseVågsætherKarlsen写道: 对此表示抱歉,以下修订版: def prientiter(value): it = iter(value) 尝试: 返回it.next(), 除了停止,错误: 没有返回,没有 def cmpfirstwith(比较): def比较(a,b): 返回比较(A [0],B [0]) 返回比较 def inorder(比较, *args): 迭代器= [ [value,it] 对于(value,it),在[Args中的ARG]中的[ARG)] 如果不是 这是给予的 iterators.sort() 迭代器时: 产生迭代器[0] [0] 尝试: 值=迭代器[0] [0] =迭代器[0] [1] .next() 除了停止,错误: 迭代器.pop(0) 别的: 如果Len(迭代器)> 1和比较(值, 迭代器[1] [0])== 1: iterators.sort(cmpfirstwith(比较)) 继续 如果__name__ ==" __ -main __": S1 = [10,20,30,40,50] S2 = [15,25] S3 = [17,27,37] S4 = [] 为Inorder(CMP,S1,S2,S3,S4)的值: 打印值 s1 = [{'a':'b'},{'a':'e'}] s2 = [{'a':'d'},{'a':'z'}] def comp(a,b): 返回CMP(a ['a'],b ['a']) 对于Inorder(CMP,S1,S2)的价值: 打印值 玩得开心, 麦克风 - - ________________________________________________________________ 迈克·C·弗莱彻(Mike C. Fletcher) 设计师,VR水管工,编码器http://www.vrplumber.com http://blog.vrplumber.com
# 回答7
LasseVågsætherKarlsen写道: 好的,在浏览了各种来源之后 解决方案,这是什么 我终于结束了: def merge_sorted(比较, *来源): 迭代= [] 来源中的来源: 尝试: source = iter(源) iterables.append([source.next(),源]) 除了停止: 经过 iterables.sort(cmp =比较,key = lambda x:x [0]) 虽然迭代: 产生迭代[0] [0] 尝试: 迭代[0] [0] =迭代[0] [1] .next() 如果len(iterables)> 1和比较(iterables [0] [0],, 迭代[1] [0])> 0: iterables.sort(比较,key = lambda x:x [0]) 除了停止: iterables.pop(0) 感谢Mike和George的解决方案和指针. - - lassevågsætherkarlsenhttp://usinglvkblog.blogspot.com/ 邮件:la ***@vkarlsen.no PGP KEYID:0x2A42A1C2
# 回答8
乔治·萨基斯(George Sakkis)写道: 在最普遍的情况下,是的. 但是,python的排序("蒂姆索尔")是 分类序列主要分类时的天然快速 除了一个元素在错误的地方...尝试一下(和 阅读Python的来源中包含的Timbot的文章和来源 自己)...我怀疑Heapq仍然会更快,但是 没有人想象的尽可能多. 是的,内置堆不进行比较操作有点不便,但是您可以通过将每个项目转换为(键,项目)元组来轻松滚动自己的堆. 现在我正在考虑,这可能是食谱的一个很好的补充. 我相信Python 2.5在Heapq的函数中添加了一个键=参数... Alex
# 回答9
亚历克斯·马特利(Alex Martelli)写道: 只是阅读建议. 翻译的PYPY来源 pypy/objectspace/listsort.py可能比 相应的C代码. 凯
# 回答10
Kay Schluehr写道:只是阅读建议. 翻译的PYPY源pypy/objectspace/listSort.py比相应的C代码更容易访问. 的确. 它在http://codespeak.net/svn/pypy/dist/p...td/listsort.py.py 干杯, Carl Friedrich Bolz
# 回答11
[Alex Martelli] [Kay Schluehr]只是阅读建议. 翻译的PYPY源pypy/objectspace/listSort.py比相应的C代码更容易访问. [CFBOLZ]的确. 它在http://codespeak.net/svn/pypy/dist/p...td/listsort.py.py 虽然Python版本当然更容易阅读,但我相信Alex 考虑到算法的详细英语_explanation_:http://cvs.sf.net/viewcvs.py/python/...s/listsort.txt 这是一种复杂的算法,滴着没有的微妙之处 从盯着实施中明显看出. 请注意,如果列表具有n个元素,则对其进行排序至少需要N-1 比较,因为那是所需的最小比较数 仅仅是为了确定是否已经分类. 基于堆的 优先队列不需要超过O(log(n))与推送或 弹出一个元素. 如果n很小,那就不会有太大的区别. 作为 n变得更大,堆的优势增长而没有界限.
# 回答12
亚历克斯·马特利(Alex Martelli)写道: 我相信python 2.5添加了一个键=他的参数 APQ的功能... 然后,当2.5发布时,我将重新访问HAEPQ解决方案. 感谢您的注意. 目前,我将留在清单上 Mike提出的解决方案略有更改为适应技巧和 该线程中其他人的指针. - - lassevågsætherkarlsenhttp://usinglvkblog.blogspot.com/ 邮件:la ***@vkarlsen.no PGP KEYID:0x2A42A1C2
# 回答13
" lassevågsætherKarlsen" 写道: 我相信Python 2.5在Heapq的函数中添加了一个键=参数... 我将在2.5发布时重新访问HAEPQ解决方案. 感谢您的注意. 目前,我将继续使用列表解决方案,迈克(Mike)提出了略微更改以适应该线程中其他人的技巧和指针. 刚刚在http://aspn.activestate.com/aspn/coo.../recipe/440673上添加了食谱. 你可以试试 两者都看看您的数据是否有任何显着的性能差异. 乔治
# 回答14
乔治·萨基斯(George Sakkis)写道: 谢谢,稍后再看一下. 排序解决方案似乎有效 很好. 如果我有很多来源,可能会有很大的区别 打赌开销的开销要比做一个n个项目要高 操纵堆将物品放在正确的位置,但有4-5 或更多来源可能根本不会产生影响. - - lassevågsætherkarlsenhttp://usinglvkblog.blogspot.com/ 邮件:la ***@vkarlsen.no PGP KEYID:0x2A42A1C2
# 回答15
" lassevågsætherKarlsen" 写道:谢谢,谢谢,稍后再看一下. 排序解决方案似乎效果很好. 如果我有很多来源,可能会有很大的区别 很少有来源可能根本不会产生影响. 除非您谈论数百或数千个来源,否则可能 惯于. 我仍然会去寻求堆解决方案,因为IMO由此产生 代码更容易理解,更易于理解. 乔治
# 回答16
乔治·萨基斯(George Sakkis)写道: ...除非您谈论数百或数千个来源,否则可能不会. 我仍然会选择堆解决方案,因为IMO生成的代码更可读性和更易于理解. 我对任何一个句子都不确定...: 海伦:〜/pynut/samp alex $ python合并.py- -numstreams = 10 -Minlen = 100 -h-how = s 10循环的最佳时间:0.24711608867 海伦:〜/pynut/samp alex $ python合并.py- -numstreams = 10 -Minlen = 100 -h-how = h 10循环的最佳时间:0.10344004631 即,堆解决方案的速度可能比基于排序的解决方案快4倍 (在以下实现中). 可读性似乎很可比 (跳过其余基础架构,生成随机排序 流并确保流耗尽并验证它等): DEF MERGE_BY_SORT(流): sources = [[s.next(),i,s.next] for i,s in Enumerate(streams)] 来源: sources.sort(反向= true) best_source = sources [-1] 产生best_source [0] 尝试:best_source [0] = best_source [-1]() 除了停止:sources.pop() def merge_by_heap(流): sources = [[s.next(),i,s.next] for i,s in Enumerate(streams)] Heapq.heapify(来源) 来源: best_source =源[0] 产生best_source [0] 尝试:best_source [0] = best_source [-1]() 除了停止:HAEPQ.HEAPPOP(来源) else:heapq.heapreplace(来源,best_source) 嗯,我想知道像Merge_by_heap这样的事情是否会成为一个很好的候选人 对于Itertool. 雷蒙德...? Alex
# 回答17
" Alex Martelli" 写道:我对任何一个句子都不确定...:〜/pynut/samp alex $ python $ python merger.py-numstreams = 10- -minlen = 100 -how = S的最佳时间10循环:0.247116088867 Helen:〜/pynut/samp alex $ python $ python合并. 0.10344004631即,堆解决方案的速度可能比基于排序的解决方案快4倍(在以下实现中). 有趣的; 我以为蒂姆索尔(Timsort 堆. 尽管如此,0.10344超过4倍的0.10344比0.247116的速度快4倍? 可读性似乎相当可比(跳过其余基础架构,该基础架构生成随机排序的流并确保流耗尽并验证它等等) 下一个]对于i,在枚举中(流)中的s]当源:sources.sort(reverse = true)best_source = source [-1]产生best_source [0] try:best_source [0] = best_source [-1]()() stopiteration:sources.pop()def merge_by_heap(streams):sources = [[s.next(),i,s.next] for e,e,e e e e e e e e emumerate(streams)] heapq.heapify(sources)时:sources:best_source = sounces [0]产生best_source [0]尝试:best_source [0] = best_source [-1]()除stopiteration:heapq.heappop(sources)else:heapq.heapreplace(sources,sources,best_source) 确实,就可读性而言,这些几乎相当. 线程中的先前示例 不太清楚. 顺便说一句,为什么您需要"我"并在上面枚举? 嗯,我想知道像Merge_by_heap这样的事情是否会成为Itertool的好候选人. 雷蒙德...? 亚历克斯 是的,将其分为2.5会很高兴. 乔治
# 回答18
亚历克斯·马特利(Alex Martelli)写道: ... 即,堆解决方案的速度可能比基于排序的解决方案快4倍(在以下实现中). 可读性似乎相当可比(跳过其余基础架构,该基础架构生成随机分类并确保流耗尽并验证它等): 要记住的一件事(如果您关心表现)是您 一个人可以使用二等,而不是排序,因为流的排序列表是 为了使您正在处理的一个元素除外. 顺便说一句,很好 反向的技巧以减少记忆复制,什么时候得到 引入? 想知道是否可以处理反向分数的元素. 无论如何,应该减少 操作的那部分的O复杂性, 虽然您仍然必须做一个纪念物才能移动其余的源 列表的数组,如果无法处理反向排序的列表 将您移回到列表前弹出. 哦,我们仍然缺少在两个版本中使用比较功能. 我认为您想要该功能 *可用 *如果您要去 使其成为一般工具. 您还需要检查停止 关于为空序列创建源. 最后,为什么"我" 元素? 它从未使用过Afaics. def merge_by_sort(streams):sources = [[s.next(),i,s.next] for i,s in Enumerate(streams)] ersices:sourceces.sorc.sort(recters = true)best_source = sources [-1] 产生best_source [0]尝试:best_source [0] = best_source [-1]()除stopiteration:source.pop() ... 玩得开心, 麦克风 - - ________________________________________________________________ 迈克·C·弗莱彻(Mike C. Fletcher) 设计师,VR水管工,编码器http://www.vrplumber.com http://blog.vrplumber.com
# 回答19
乔治·萨基斯(George Sakkis)写道: ... 糟糕,2.5次(用于10个流) - 比率不断越来越大 我想到的溪流数,可能来自 与50个流左右的比较. 即使已经订购了列表,Timsort也需要n比较(只是 检查它是),而堆可以使用日志(n)比较甚至更少 最好的情况 - 这是这里的关键问题. ...的确,就可读性而言,这些几乎相当. 线程中的先前示例不太清楚. 顺便说一句,为什么您需要"我"并在上面枚举? 确保,如果第一项相同,则分类(或 堆的比较)不比较_methods_-如果它没什么大不了的 确实,但这在逻辑上没有意义. 如果我们有键=参数, 这将无法确保这种比较,但是堆不支持 2.4我想保持比赛场水平,所以我使用了以上 确保稳定排序的旧技巧,而没有比较超出给定的 字段(在第一版的食谱中解释了更多详细信息, 但我希望我给出一个总体的想法). Alex
# 回答20
Mike C. Fletcher 写道: ... 列表的词典比较使用了第一元素的词典比较 比较的两个列表中有相等(当然可以发生) 避免比较最后元素(这是方法...如果 他们得到了比较,但这没有逻辑上的意义). 因此,一个示例增强了merge_by_sort: def merge_by_sort(流,键=无): 如果不是键:key = lambda x:x 来源= [] 对于i,s中的s(流): 尝试:first_item = s.next() 除了停止:通过 else:sources.append(((键(项目),i,item,s.next))) 来源: sources.sort(反向= true) best_source = sources [-1] 产生best_source [2] 尝试:best_source [2] = best_source [-1]() 除了停止:sources.pop() else:best_source [0] = key(best_source [2]) 当然,由于排序方法确实接受键= par 阿默特,这个 可以简化,但我会这样,以使其变得微不足道 请参阅如何通过堆(在2.4中)回顾合并的方法... Alex
# 回答21 这种方法的另一个想法是,在某些情况下,我注意到 知道每个元素也来自哪个来源,这很有用 以及从结果中删除重复. 例如 S1 = [1,3,5,7] S2 = [2,3,4] 对于k,s merge_by_sort(s1,s2): 打印k,"来自源",s 这将打印: 1来自源0 2来自源1 来自源1的3 3来自来源0 来自源1的4 5来自来源0 7来自来源0 上面的列表有3次,因此可能是: 1来自来源[0] 2来自来源[1] 3来自来源[0,1] 4来自来源[1] 5来自来源[0] 7来自来源[0] 后一个将是一种更为重的方法 比较列表或堆的n个第一个元素以弄清楚什么 也要屈服的指数. 但是,以前的解决方案可能是: def merge_by_sort(*源,**选项): 如果选项中的" cmp": 比较=选项[" CMP"] 别的: 比较= CMP 迭代= [] 对于索引,枚举中的来源(来源): 尝试: source = iter(源) iterables.append([source.next(),索引,源]) 除了停止: 经过 iterables.sort(cmp =比较,key = lambda x:x [0],反向= true) 虽然迭代: 产生迭代[-1] [0],迭代[-1] [1] 尝试: 迭代[-1] [0] = iTerables [-1] [2] .next() 如果len(iterables)> 1和比较(iterables [-1] [0],, 迭代[-2] [0])> 0: iterables.sort(比较,key = lambda x:x [0],, 反向= true) 除了停止: iterables.pop(-1) - - lassevågsætherkarlsenhttp://usinglvkblog.blogspot.com/ 邮件:la ***@vkarlsen.no PGP KEYID:0x2A42A1C2
# 回答22
LasseVågsætherKarlsen写道: "删除重复"问题可能是一个单独的 功能,在我看来,也许Python具有这样的功能 已经. 同样,此功能将需要以下标准: 1.能够通过清单以外的其他内容进行迭代 2.产生值,而不是返回列表 3.采用任意CMP功能来确定什么是重复 作为糖,也许也是以下标准: - 能够通过特殊功能"组合"重复项 我一起入侵的一个简单的第一反面函数可以做到这一点: def unique(源,cmp = cmp,key = none,combine = none): it = iter(源) 首先= true 值= it.next() 值= [值] 而真: 尝试: 值= it.next() 如果键不是没有: cmp_result = cmp(values [0] [key],value [key]) 别的: cmp_result = cmp(值[0],value) 如果cmp_result == 0: values.append(value) 别的: 如果结合不是没有: 产量组合(值) 别的: 产量值[0] 值= [值] 除了停止: 如果结合不是没有: 产量组合(值) 别的: 产量值[0] 休息 提高止动 请注意,此功能不进行任何排序,因此如果来源是 从中获取值没有排序,结果将是非常错误的. 这个 再次由于m 能够处理光标检索的标准 来自数据库的数据,从而避免将所有内容加载到内存中. 联合函数通过"重复"值的列表,必须 返回一个将从唯一的值所产生的值. 用法的示例: def sum_counts(值): 值=值[0] [0] 总和= 0 对于值的行: sum +=行[1] 返回值,总和 水果= [["苹果",10],["苹果",15],["香蕉",23],["橙色",17], ["橙色",17]] 对于水果,唯一的total_sum(水果,键= 0,combine = sum_counts): 打印水果,"有一个总和",total_sum 这将产生: 苹果的总和25 香蕉的总和23 橙子的总和为34 功能名称也许不是最好的名称. 在我看来,这是 SQL中逐函数的组,所以也许其他名称更好,但是 然后,如果这样的功能已经存在某个地方,那么这可能会有障碍:) - - lassevågsætherkarlsenhttp://usinglvkblog.blogspot.com/ 邮件:la ***@vkarlsen.no PGP KEYID:0x2A42A1C2
# 回答23
>功能名称也许不是最好的名称. 在我看来,这是 令人惊讶的是,即使有完全相同的名字,您也会不断重塑事物:) 从Itertools导入IMAP,Groupby 从操作员导入itemgetter 对于果实,集团在Groupby(水果,itemgetter(0)): 打印水果,"有一个总和",总和(imap(itemgetter(1),组)) 为了按预期工作,必须已经对 给格鲁比的钥匙相同; 否则,只需用 排序(水果,itemgetter(0)). 顺便说一句,读取Itertools模块中的所有功能 (http://docs.python.org/lib/itertools-functions.html),它将为您保存 很多时间. 乔治
# 回答24
乔治·萨基斯(George Sakkis)写道: 令人惊讶的是,即使以完全相同的名称,您也会继续重塑:)从Itertools Import Imap,从运营商Import Import for Fruit的Groupby,Groupby中的Groupby(水果,Itemgetter(0)):打印水果,"有"," 为了按预期工作,sum(imap(itemgetter(1),组))必须按照给格鲁比的相同键进行排序; 否则,只需将水果替换为排序(水果,itemgetter(0)). 顺便说一句,读取Itertools模块中的所有功能(http://docs.python.org/lib/itertools-functions.html),它将为您节省很多时间. 乔治 Itertools,嗯,又有那个轮子:) 不知道这个,所以谢谢:) - - lassevågsætherkarlsenhttp://usinglvkblog.blogspot.com/ 邮件:la ***@vkarlsen.no PGP KEYID:0x2A42A1C2
标签: python