嵌套列表上的Itertools链

时间:2016-09-25 21:05:04

标签: python python-3.x

我有两个列表顺序组合,用python的map和zip funcionality创建一个嵌套列表;但是,我希望用itertools重新创建它。

此外,我试图理解为什么当我插入两个列表时itertools.chain返回一个展平列表,但是当我添加一个嵌套列表时,它只返回嵌套列表。

对这两个问题的任何帮助将不胜感激。

from tkinter import *

global widgets # this list will contain widgets to be deleted
widgets = []
def square():
    global widgets
    for widget in widgets[:]:
        widget.destroy()
        widgets.remove(widget)

    ment = IntVar()
    def mhello():
        mtext = ment.get()
        mtext *= 2
        mlabel2 = Label(mGui, text=mtext)

    mlabel = Label(mGui, text="Square")
    mbutton = Button(mGui, text= "Submit", command = mhello)

    nEntry = Entry(mGui, textvariable=ment)
    widgets = widgets[:] + [mlabel, mbutton, nEntry] # destroy these later

    for widget in widgets:
        widget.pack() # pack them afterwards

def rectangle():
    global widgets
    for widget in widgets[:]:
        widget.destroy()
        widgets.remove(widget)

    oneMent = IntVar()
    twoMent = IntVar()
    def mhello():
        oneMtext = oneMent.get()
        twoMtext = twoMent.get()
        mtext = 0
        mtext = oneMtext * twoMtext
        mlabel2 = Label(mGui, text=mtext).pack()

    mlabel = Label(mGui, text="Rectangle/Parallelogram")

    mbutton = Button(mGui, text= "Submit", command = mhello)

    oneEntry = Entry(mGui, textvariable=oneMent)
    twoEntry = Entry(mGui, textvariable=twoMent)
    widgets = widgets + [mlabel, mbutton, oneEntry, twoEntry] # destroy these later
    for widget in widgets:
        widget.pack() # pack them afterwards

def trapezium():
    global widgets
    for widget in widgets[:]:
        widget.destroy()
        widgets.remove(widget)

    oneMent = IntVar()
    twoMent = IntVar()
    threeMent = IntVar()
    def mhello():
        oneMtext = oneMent.get()
        twoMtext = twoMent.get()
        threeMtext = threeMent.get()
        mtext = 0
        mtext = oneMtext + twoMtext
        mtext /= 2
        mtext *= threeMtext

        mlabel2 = Label(mGui, text=mtext).pack()

    mlabel = Label(mGui, text="Trapezium")

    mbutton = Button(mGui, text= "Submit", command = mhello)

    oneEntry = Entry(mGui, textvariable=oneMent)
    twoEntry = Entry(mGui, textvariable=twoMent)
    threeEntry = Entry(mGui, textvariable=threeMent)
    widgets = widgets + [mlabel, mbutton, oneEntry, twoEntry, threeEntry] # destroy these later
    for widget in widgets:
        widget.pack() # pack them afterwards

def rhombus():
    global widgets
    for widget in widgets[:]:
        widget.destroy()
        widgets.remove(widget)

    oneMent = IntVar()
    twoMent = IntVar()
    def mhello():
        oneMtext = oneMent.get()
        twoMtext = twoMent.get()
        mtext = 0
        mtext = oneMtext * twoMtext
        mtext /= 2

        mlabel2 = Label(mGui, text=mtext).pack()

    mlabel = Label(mGui, text="Rhombus")

    mbutton = Button(mGui, text= "Submit", command = mhello)

    oneEntry = Entry(mGui, textvariable=oneMent)
    twoEntry = Entry(mGui, textvariable=twoMent)
    widgets = widgets + [mlabel, mbutton, oneEntry, twoEntry] # destroy these later
    for widget in widgets:
        widget.pack() # pack them afterwards

def restart():
    mGui.destroy()


mGui = Tk()

mGui.geometry("450x450+500+300")
mGui.title("Square Area Finder")
mHomeLabel = Label(mGui, text="Use the drop down menu to select the quadrilateral you want to find the area of.").pack()
menu = Menu(mGui)
mGui.config(menu=menu)
file =Menu(menu)
file.add_command(label="Square", command=square)
file.add_command(label="Rectangle/Parallelogram", command=rectangle)
file.add_command(label="Trapezium", command=trapezium)
file.add_command(label="Rhombus", command=rhombus)
file.add_separator()
file.add_command(label="Quit", command=restart)
menu.add_cascade(label="Options", menu=file)

mGui.mainloop()

1 个答案:

答案 0 :(得分:2)

我会尽力回答你的问题。

首先,itertools.chain不会像您认为的那样发挥作用。 chain需要x次迭代,并按顺序迭代它们。当您调用chain时,它基本上(内部)将对象打包到列表中:

chain("ABC", "DEF") # Internally creates ["ABC", "DEF"]

在方法内部,它一次访问一个项目,并迭代它们:

for iter_item in arguments:
    for item in iter_item:
        yield item

因此,当您调用chain([[a,b],[c,d,e],[f,g]])时,它会创建一个包含一个可迭代对象的列表:您作为参数传递的列表。所以现在它看起来像这样:

[ #outer
    [ #inner
        [a,b],
        [c,d,e],
        [f,g]
    ]
]

chain因此迭代内部列表,并按顺序返回三个元素:[a,b][c,d,e][f,g]。然后他们被{​​{1}}重新包装,给你最初的东西。

顺便提一下,有一种方法可以做你想做的事:list。这是chain.from_iterable的替代构造函数,它接受单个迭代(例如列表),并将元素拉出以进行迭代。所以不要这样:

chain

你明白了:

# chain(l)
[ #outer
    [ #inner
        [a,b],
        [c,d,e],
        [f,g]
    ]
]

这将迭代三个子列表,并按一个序列返回它们,因此# chain.from_iterable(l) [ [a,b], [c,d,e], [f,g] ] 将返回list(chain.from_iterable(l))

至于你的第二个问题:虽然我不知道为什么[a,b,c,d,e,f,g]是这个过程的必要条件,但你可以在Python 2.x中这样做:

itertools

但是,在3.x中,list(itertools.izip(x,y))功能已被删除。仍有izip,它会匹配尽可能多的对,并接受额外对的填充值:zip_longest返回list(zip_longest([a,b,c],[d,e,f,g,h],fillvalue="N")),因为第二个列表比第一个更长。正常[(a,d),(b,e),(c,f),(N,g),(N,h)]将采用最短的可迭代并切断其余部分。

换句话说,除非您想要zip而不是zip_longest,否则zip没有内置的压缩​​方法。