【python】itertools—创建用于高效循环的迭代器的函数

一、简介

该模块标准化了一套快速的,内存高效的工具的核心集,这些工具本身或结合使用很有用。它们共同构成了一个“迭代器代数”,从而可以在纯Python中简洁高效地构建专用工具。

itertools模块官网介绍

二、常用方法介绍

在这里插入图片描述

2.1.获取嵌套循环结果product()

输入可迭代项的笛卡尔积

大致等效于生成器表达式中的嵌套for循环。例如, 返回与相同的结果。product(A, B)((x,y) for x in A for y in B)

嵌套循环就像里程表一样循环,最右边的元素在每次迭代中都前进。此模式创建字典顺序,以便如果对输入的可迭代对象进行排序,则将按排序顺序发出产品元组。

itertools.product(* iterables,repeat = 1 )

举例:

product('ABCD', repeat=2)

#AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD

等效代码:

此函数大致等效于以下代码,不同之处在于实际实现不会在内存中建立中间结果:

def product(*args, repeat=1):
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
    pools = [tuple(pool) for pool in args] * repeat
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)
2.2.获取指定长度的全排列方法permutations()
返回iterable中元素的连续r长度排列。

itertools.permutations(iterable, r=None)

举例:

permutations('ABCD', 2)

#AB AC AD BA BC BD CA CB CD DA DB DC

内部代码实现

def permutations(iterable, r=None):
    # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
    # permutations(range(3)) --> 012 021 102 120 201 210
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    if r > n:
        return
    indices = list(range(n))
    cycles = list(range(n, n-r, -1))
    yield tuple(pool[i] for i in indices[:r])
    while n:
        for i in reversed(range(r)):
            cycles[i] -= 1
            if cycles[i] == 0:
                indices[i:] = indices[i+1:] + indices[i:i+1]
                cycles[i] = n - i
            else:
                j = cycles[i]
                indices[i], indices[-j] = indices[-j], indices[i]
                yield tuple(pool[i] for i in indices[:r])
                break
        else:
            return
2.3.按排序顺序,没有重复的元素combinations()
itertools.combinations(iterable, r)

r长度元组,按排序顺序,没有重复的元素
举例:

combinations('ABCD', 2)

#AB AC AD BC BD CD

根据输入iterable的顺序,按字典顺序发出组合元组。因此,如果对输入的iterable进行排序,则将按排序顺序生成组合元组。

元素根据其位置而不是其价值被视为唯一。因此,如果输入元素是唯一的,则每个组合中都不会有重复值。

相当于

def combinations(iterable, r):
    # combinations('ABCD', 2) --> AB AC AD BC BD CD
    # combinations(range(4), 3) --> 012 013 023 123
    pool = tuple(iterable)
    n = len(pool)
    if r > n:
        return
    indices = list(range(r))
    yield tuple(pool[i] for i in indices)
    while True:
        for i in reversed(range(r)):
            if indices[i] != i + n - r:
                break
        else:
            return
        indices[i] += 1
        for j in range(i+1, r):
            indices[j] = indices[j-1] + 1
        yield tuple(pool[i] for i in indices)

的代码combinations()还可以表示为permutations()元素过滤后的子序列,其中元素未按顺序排列(根据它们在输入池中的位置):

def combinations(iterable, r):
    pool = tuple(iterable)
    n = len(pool)
    for indices in permutations(range(n), r):
        if sorted(indices) == list(indices):
            yield tuple(pool[i] for i in indices)
2.4.按排序顺序,有重复的元素combinations_with_replacement()

输入可迭代返回元素的r长度子序列, 允许单个元素重复多次。

itertools.combinations_with_replacement(iterable, r)

举例:

combinations_with_replacement('ABCD', 2)

#AA AB AC AD BB BC BD CC CD DD

根据输入iterable的顺序,按字典顺序发出组合元组。因此,如果对输入的iterable进行排序,则将按排序顺序生成组合元组。

元素根据其位置而不是其价值被视为唯一。因此,如果输入元素是唯一的,则生成的组合也将是唯一的。

大致相当于:

def combinations_with_replacement(iterable, r):
    # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC
    pool = tuple(iterable)
    n = len(pool)
    if not n and r:
        return
    indices = [0] * r
    yield tuple(pool[i] for i in indices)
    while True:
        for i in reversed(range(r)):
            if indices[i] != n - 1:
                break
        else:
            return
        indices[i:] = [indices[i] + 1] * (r - i)
        yield tuple(pool[i] for i in indices)

的代码combinations_with_replacement()还可以表示为product()元素过滤后的子序列,其中元素未按顺序排列(根据它们在输入池中的位置):

def combinations_with_replacement(iterable, r):
    pool = tuple(iterable)
    n = len(pool)
    for indices in product(range(n), repeat=r):
        if sorted(indices) == list(indices):
            yield tuple(pool[i] for i in indices)

返回的项目的数量时。(n+r-1)! / r! / (n-1)!n > 0

三、应用-24点游戏算法:

问题描述:给出4个1-10的数字,通过加减乘除,得到数字为24就算胜利

import sys
import itertools

def func(cards):
    for nums in itertools.permutations(cards): # 四个数
        for ops in itertools.product('+-*/', repeat=3): # 三个运算符(可重复!)
            # 构造三种中缀表达式 (bsd)
            bds1 = '({0}{4}{1}){5}({2}{6}{3})'.format(*nums, *ops)  # (a+b)*(c-d)
            bds2 = '(({0}{4}{1}){5}{2}){6}{3}'.format(*nums, *ops)  # (a+b)*c-d
            bds3 = '{0}{4}({1}{5}({2}{6}{3}))'.format(*nums, *ops)  #  a/(b-(c/d))
            
            for bds in [bds1, bds2, bds3]: # 遍历
                try:
                    if abs(eval(bds) - 24.0) < 1e-10:   # eval函数
                        return 'true'
                except ZeroDivisionError: # 零除错误!
                    continue
    return 'false'

for line in sys.stdin:
    nums = list(map(int, line.strip().split()))
    print(str(func(nums)).lower())

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值