【问题标题】:Python loop through 2 listsPython 循环遍历 2 个列表
【发布时间】:2014-06-26 13:16:39
【问题描述】:

我正在用 Python 编写一些几乎可以工作的代码,但有一件事我无法弄清楚。

我需要遍历 2 个列表。我想循环直到第一个列表完成;而第二个列表应该不断重复,直到第一个列表完成。

我想输入一个数据库列表和一个流列表。然后我希望代码通过替换“+流+”和“+项目+”的位置来输出9行。 item 部分工作正常,但我不知道如何在遍历数据库列表时输出流列表。我希望流循环然后重复。所以它将从 1a 开始,然后到达 3c,然后在 1a 重新开始。我希望这种情况一直发生,直到它到达列表中的最后一个数据库。

databases=input("Enter databases: ")
streams="1a 2a 3a 1b 2b 3b 1c 2c 3c"
stream="1a"

db_list = databases.split()
streams_list= streams.split()

for item in db_list:
    print("unlink $ORACLE_BASE/admin/" + item + "/backup")
    print("unlink $ORACLE_BASE/admin/" + item + "/dpdump")
    print("unlink $ORACLE_BASE/admin/" + item + "/exp")
    print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/backup")
    print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump")
    print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/exp")
    print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/backup $ORACLE_BASE/admin/" + item + "/backup")
    print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump $ORACLE_BASE/admin/" + item + "/dpdump")
    print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/exp    $ORACLE_BASE/admin/" + item + "/exp")

这是输出:

Enter databases: database1 database2 database3
unlink $ORACLE_BASE/admin/database1/backup
unlink $ORACLE_BASE/admin/database1/dpdump
unlink $ORACLE_BASE/admin/database1/exp
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database1/backup
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database1/dpdump
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database1/exp
ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database1/backup $ORACLE_BASE/admin/database1/backup
ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database1/dpdump $ORACLE_BASE/admin/database1/dpdump
ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database1/exp    $ORACLE_BASE/admin/database1/exp
unlink $ORACLE_BASE/admin/database2/backup
unlink $ORACLE_BASE/admin/database2/dpdump
unlink $ORACLE_BASE/admin/database2/exp
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database2/backup
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database2/dpdump
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database2/exp
ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database2/backup $ORACLE_BASE/admin/database2/backup
ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database2/dpdump $ORACLE_BASE/admin/database2/dpdump
ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database2/exp    $ORACLE_BASE/admin/database2/exp
unlink $ORACLE_BASE/admin/database3/backup
unlink $ORACLE_BASE/admin/database3/dpdump
unlink $ORACLE_BASE/admin/database3/exp
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database3/backup
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database3/dpdump
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM1a/database3/exp
ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database3/backup $ORACLE_BASE/admin/database3/backup
ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database3/dpdump $ORACLE_BASE/admin/database3/dpdump
ln -s $ORACLE_BASE/acfsmounts/global/STREAM1a/database3/exp    $ORACLE_BASE/admin/database3/exp

我的输出每次都有 STREAM1a,但我希望它在 1a、2a、3a、1b、2b、3b、1c、2c 和 3c 的模式中循环。如前所述,如果我有超过 9 个数据库,那么它将再次从 1a 开始。我怎样才能做到这一点?

我的代码中唯一没有按我想要的方式工作的部分是它显示“+流+”的地方。

【问题讨论】:

  • 您是否希望它循环遍历db_list 中每个项目的所有streams?比如database1 1adatabase1 2adatabase1 3a等等?
  • 是的,这正是我想要的。当它到达 database9 时,它将处于 3c。当它到达 database10 时,它需要回到 1a。
  • 可能是一个生成器函数

标签: python list loops output


【解决方案1】:

您应该使用itertools.cycle。这将允许您在无休止的重复循环中获取列表的元素。在循环开始处添加此代码:

stream_cycle = itertools.cycle(streams_list)
for item in db_list:
    stream = stream_cycle.next()

或者按照@HughBothwell 的建议,您可以使用 zip 并将其包含在for 循环的定义中:

for item, stream in zip(db_list, itertools.cycle(streams_list)):

无论哪种方式都会在循环的每次迭代中为您提供下一个流。如果你的 dbs 多于流,那么它会重复。

【讨论】:

  • ... 或 for item,stream in zip(db_list, itertools.cycle(stream)):
  • 好建议。我已经添加进去了。
  • 我收到错误:ImportError: cannot import name 'izip'
  • @user2554129 是的,izip 在 Python 3 中不存在。这就是我在示例中使用 zip 而不是 izip 的原因。你也不需要导入它。
  • 效果很好!谢谢! :) 有没有办法让我分享我完成的代码以防有人感兴趣?
【解决方案2】:

诀窍是使用来自itertools 的迭代器,称为cycle

from itertools import cycle
databases=input("Enter databases: ")
streams="1a 2a 3a 1b 2b 3b 1c 2c 3c"
stream="1a"

db_list = databases.split()
stream_list= streams.split()

for item, stream in zip(db_list, cycle(stream_list)):
    print("unlink $ORACLE_BASE/admin/" + item + "/backup")
    print("unlink $ORACLE_BASE/admin/" + item + "/dpdump")
    print("unlink $ORACLE_BASE/admin/" + item + "/exp")
    print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/backup")
    print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump")
    print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/exp")
    print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/backup $ORACLE_BASE/admin/" + item + "/backup")
    print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump $ORACLE_BASE/admin/" + item + "/dpdump")
    print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/exp    $ORACLE_BASE/admin/" + item + "/exp")

bonus - 使用 docopt 解析命令行参数

小红包:让你调用脚本,方便地从命令行输入参数

安装docopt 包(只需一次)

$ pip install docopt

编写脚本的修改版本db.py

"""Usage:
    db.py -s <stream> (-s <stream>)... <db> <db>...
    db.py -h

For all database names <db> generates commands combining it with
names of <stream>s.
"""
from docopt import docopt
from itertools import cycle   

args = docopt(__doc__)

db_list = args["<db>"]
stream_list = args["<stream>"]

for item, stream in zip(db_list, cycle(stream_list)):
    print("unlink $ORACLE_BASE/admin/" + item + "/backup")
    print("unlink $ORACLE_BASE/admin/" + item + "/dpdump")
    print("unlink $ORACLE_BASE/admin/" + item + "/exp")
    print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/backup")
    print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump")
    print("mkdir -p /oradba/app/oracle/acfsmounts/global/STREAM" + stream + "/" + item + "/exp")
    print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/backup $ORACLE_BASE/admin/" + item + "/backup")
    print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/dpdump $ORACLE_BASE/admin/" + item + "/dpdump")
    print("ln -s $ORACLE_BASE/acfsmounts/global/STREAM" + stream + "/" + item + "/exp    $ORACLE_BASE/admin/" + item + "/exp")

打印输出使用字符串:

$ python db.py
Usage:
    db.py -s <stream> (-s <stream>)... <db> <db>...
    db.py -h

显示一些帮助字符串:

$ python db.py -h
Usage:
    db.py -s <stream> (-s <stream>)... <db> <db>...
    db.py -h

For all database names <db> generates commands combining it with
names of <stream>s.

并称其为实际用途:

$ python db.py -s s2 -s s2 db1 db2 db3
unlink $ORACLE_BASE/admin/db1/backup
unlink $ORACLE_BASE/admin/db1/dpdump
unlink $ORACLE_BASE/admin/db1/exp
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db1/backup
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db1/dpdump
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db1/exp
ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db1/backup $ORACLE_BASE/admin/db1/backup
ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db1/dpdump $ORACLE_BASE/admin/db1/dpdump
ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db1/exp    $ORACLE_BASE/admin/db1/exp
unlink $ORACLE_BASE/admin/db2/backup
unlink $ORACLE_BASE/admin/db2/dpdump
unlink $ORACLE_BASE/admin/db2/exp
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db2/backup
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db2/dpdump
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db2/exp
ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db2/backup $ORACLE_BASE/admin/db2/backup
ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db2/dpdump $ORACLE_BASE/admin/db2/dpdump
ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db2/exp    $ORACLE_BASE/admin/db2/exp
unlink $ORACLE_BASE/admin/db3/backup
unlink $ORACLE_BASE/admin/db3/dpdump
unlink $ORACLE_BASE/admin/db3/exp
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db3/backup
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db3/dpdump
mkdir -p /oradba/app/oracle/acfsmounts/global/STREAMs2/db3/exp
ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db3/backup $ORACLE_BASE/admin/db3/backup
ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db3/dpdump $ORACLE_BASE/admin/db3/dpdump
ln -s $ORACLE_BASE/acfsmounts/global/STREAMs2/db3/exp    $ORACLE_BASE/admin/db3/exp

【讨论】:

  • 我把“import itertools”放在顶部,然后我把“from itertools import cycle, izip”放进去。我把for循环改成了“for item, stream in zip(db_list, itertools.cycle (streams_list)):”,但我收到此错误:“ImportError:无法导入名称'izip'”。我认为这是因为我使用的是 Python 3?
  • 简,这看起来很酷!不幸的是,我将无法利用它,因为我将在数百个不同的服务器上工作。我什至不确定服务器是否有 Python。所以我可能需要在我的本地机器上运行代码。
  • @user2554129 这听起来很可怕 - 没有 Python - 没有乐趣。如果你关心最小的安装依赖,那么从 Python 2.7 开始就有内置的 argparse 模块。但是在您的机器上生成脚本并将其分发到服务器(通过 ssh?)似乎更明智。但我现在偏离了轨道。祝你好运。
猜你喜欢
  • 1970-01-01
  • 2018-10-26
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多