使用zip命令从列表列表中获取所有列表的最后一个元素

时间:2018-06-20 20:51:00

标签: python list

我有一个列表列表:

       Y= [[192, 193, 194, 195, 196, 197, 198, 199, 200],
         [507, 508, 509],
         [526, 527, 528, 529],
         [560, 561],
         [635, 636, 637]]

,我希望将每个列表的最后一个元素和第一个元素放入一个单独的列表中。 我使用了zip命令:

list(zip(*Y))[0]

所有第一个元素都给了我

[192,507,526,560,635]

但是当我使用list(zip(*Y))[-1]

我得到了[193, 508, 527, 561, 636]

代替[200,509,529,561,637]

我在做什么错了?

2 个答案:

答案 0 :(得分:3)

您已经关闭-只需使用反向列表迭代器即可:

@SpringComponent
@UIScope
public class ContactEditor extends VerticalLayout {

    private final ContactRepository repository;

    private Contact contact;

    TextField firstName = new TextField("First name");
    TextField lastName = new TextField("Last name");
    TextField phoneNumber = new TextField("Phone number");
    TextField phoneType = new TextField( "Phone type");

    Button save = new Button("Save", VaadinIcons.CHECK);
    Button cancel = new Button("Cancel");
    Button delete = new Button("Delete", VaadinIcons.TRASH);
    CssLayout actions = new CssLayout(save, cancel, delete);

    Binder<Contact> binder = new Binder<>(Contact.class);


    @Autowired
    public ContactEditor(ContactRepository repository, Contact contact) {
        this.repository = repository;
        this.contact = contact;
        String type = contact.getPhoneType().getType();

        addComponents(firstName, lastName, phoneNumber, phoneType, actions);

        // bind using naming convention
        **binder.bind(phoneType, contact.getPhoneType().getType(), contact.getPhoneType().setType(type));**
        binder.bindInstanceFields(this);

        // Configure and style components
        setSpacing(true);
        actions.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
        save.setStyleName(ValoTheme.BUTTON_PRIMARY);
        save.setClickShortcut(ShortcutAction.KeyCode.ENTER);

        // wire action buttons to save, delete and reset
        save.addClickListener(e -> repository.save(contact));
        delete.addClickListener(e -> repository.delete(contact));
        cancel.addClickListener(e -> editContact(contact));
        setVisible(false);
    }

    public interface ChangeHandler {

        void onChange();
    }

    public final void editContact(Contact c) {
        if (c == null) {
            setVisible(false);
            return;
        }
        final boolean persisted = c.getId() != null;
        if (persisted) {
            // Find fresh entity for editing
            contact = repository.findById(c.getId()).get();
        }
        else {
            contact = c;
        }
        cancel.setVisible(persisted);

        // Bind customer properties to similarly named fields
        // Could also use annotation or "manual binding" or programmatically
        // moving values from fields to entities before saving
        binder.setBean(contact);

        setVisible(true);

        // A hack to ensure the whole form is visible
        save.focus();
        // Select all text in firstName field automatically
        firstName.selectAll();
    }

    public void setChangeHandler(ChangeHandler h) {
        // ChangeHandler is notified when either save or delete
        // is clicked
        save.addClickListener(e -> h.onChange());
        delete.addClickListener(e -> h.onChange());
    }


}

或更直接地,列表理解:

>>> list(zip(*[reversed(y) for y in Y]))[0]
(200, 509, 529, 561, 637)

答案 1 :(得分:2)

zip压缩相同长度的可迭代对象。如果给出长度不同的可迭代对象,则它会在第一个长度的结尾处停止。

因此,由于最短列表的长度为2,因此您得到了第一个元素,然后是第二个元素……就是这样,所以[-1]返回了第二个元素。

您可以使用itertools.zip_longest,但这并没有真正的帮助,因为它通过在结尾处填充额外的None值来处理不同长度的可迭代对象,而不是在中间插入额外的值。或将它们全部伸展到相同长度的东西。


最简单的方法是在压缩之前先获取每个 first 的开头和结尾:

Y= [[192, 193, 194, 195, 196, 197, 198, 199, 200],
    [507, 508, 509],
    [526, 527, 528, 529],
    [560, 561],
    [635, 636, 637]]

FL = [(sublist[0], sublist[-1]) for sublist in Y]

然后,您可以使用zip将其移置:

F, L = zip(*FL)

或者只是zip什么也没有,因为无论如何,移调并不会带来任何真正的好处,只是使事情变得更加复杂:

F = [sublist[0] for sublist in Y]
L = [sublist[-1] for sublist in Y]

或者,您可以压缩前后列表:

F = zip(*Y)
L = zip(*map(reversed, Y))

然后从每个元素中获取第一个元素:

f, l = next(F), next(L) # or list(F)[0] if you insist

我认为这与您尝试执行的操作最接近,但这似乎是最复杂的方法。