从多个字典写入单个CSV文件

时间:2018-10-22 03:59:31

标签: python csv dictionary

背景

我有多个不同长度的字典。我需要将字典的值写入单个CSV文件。我想我可以逐个循环浏览每个字典,然后将数据写入CSV。我遇到了一个小型格式化问题。

问题/解决方案

我意识到在循环浏览第一个字典之后,第二次写作的数据被写入了第一个字典结束的行,如第一张图片中所示。我理想地希望我的数据按如下所示打印在第二张图片

enter image description here enter image description here

我的代码

import csv

    e = {'Jay':10,'Ray':40}
    c = {'Google':5000}

    def writeData():
        with open('employee_file20.csv', mode='w') as csv_file:
            fieldnames = ['emp_name','age','company_name','size']
            writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
            writer.writeheader()

            for name in e:
                 writer.writerow({'emp_name':name,'age':e.get(name)})

            for company in c:
                writer.writerow({'company_name':company,'size':c.get(company)})


    writeData()

PS:我将有两个以上的词典,所以我正在寻找一种通用的方式,可以在所有词典的标题下从行打印数据。我愿意接受所有解决方案和建议。

2 个答案:

答案 0 :(得分:1)

如果所有字典的大小相同,则可以使用zip对其进行并行迭代。如果它们的大小不相等,并且您希望迭代填充到最长的字典,则可以使用itertools.zip_longest

例如:

package test45_listeners;

import java.util.function.Function;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.WeakInvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.beans.value.WeakChangeListener;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TextField;
import javafx.util.StringConverter;
import javafx.util.converter.DefaultStringConverter;

public class TestTextCell<S, T> extends TableCell<S, T> {

    public final TextField textField = new TextField();
    public final StringConverter<T> converter;

    private BooleanProperty isLockedProperty;

    private final InvalidationListener strongListener = (Observable observable) -> {
        updateStyle();
    };
    private final WeakInvalidationListener weakListener = new WeakInvalidationListener(strongListener);
/*
    public ChangeListener<Boolean> strongListener = (ObservableValue<? extends Boolean> observable, Boolean wasFocused, Boolean isNowFocused) -> {
        updateStyle();
    };
    public final WeakChangeListener<Boolean> weakListener = new WeakChangeListener<Boolean>(strongListener);
*/
    //********************************************************************************************************************* 
    public TestTextCell(StringConverter<T> converter, Function<S, BooleanProperty> methodGetLockedProperty) {

        this.converter = converter;
        setGraphic(textField);
        setContentDisplay(ContentDisplay.TEXT_ONLY);

        itemProperty().addListener((obx, oldItem, newItem) -> {
            if (newItem == null) {
                setText(null);
            } else {
                setText(converter.toString(newItem));
                if ( methodGetLockedProperty != null ) {
                    S datamodel = getTableView().getItems().get(getIndex());
                    isLockedProperty = methodGetLockedProperty.apply(datamodel);
                } else {
                    isLockedProperty = new SimpleBooleanProperty(false);
                }
            }
        });

        //Add the invalidation listener
        selectedProperty().addListener(strongListener);

    }

    //*******************************************************************************************************************    
    public static <S> TestTextCell<S, String> createStringTextCell(Function<S, BooleanProperty> methodGetLockedProperty) {
        return new TestTextCell<S, String>(new DefaultStringConverter(), methodGetLockedProperty);
    }

    //*******************************************************************************************************************    
    @Override
    protected void updateItem(T item, boolean empty) {

        T oldItem = (T) getItem();
        if (oldItem != null) {
            selectedProperty().removeListener(weakListener);
        }

        super.updateItem(item, empty);

        if (item != null) {
            selectedProperty().addListener(weakListener);

            if ( getTableRow() != null ) {
                if (getGraphic() != null) {
                    getGraphic().disableProperty().bind(
                        Bindings.not(getTableRow().editableProperty())
                    );
                }
            }
        }

    }

    @Override
    public void startEdit() {
        if ( ! isLockedProperty.get() ) {
            super.startEdit();
            if (getGraphic() != null) {
                textField.setText(converter.toString(getItem()));
                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                getGraphic().requestFocus();
            }
        }
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();
        setContentDisplay(ContentDisplay.TEXT_ONLY);
    }

    //*******************************************************************************************************************    
    private void updateStyle() {

        System.out.println("in updateStyle(), isLockedProperty = " + isLockedProperty.get() 
                + ", isSelected() = " + isSelected() + ", selectedProperty.get() = " + selectedProperty().get());
        if ( getTableRow() != null ) {
            if ( isLockedProperty.get() && isSelected() ) {
//            if ( isLockedProperty.get() && selectedProperty().get() ) {
                getTableRow().setStyle("-fx-background-color: pink;");
            } else if ( isLockedProperty.get() && ! isSelected()) {
//            } else if ( isLockedProperty.get() && ! selectedProperty().get() ) {
                getTableRow().setStyle("-fx-background-color: yellow;");
            } else if ( ! isLockedProperty.get() && isSelected() ) {
//            } else if ( ! isLockedProperty.get() && selectedProperty().get() ) {
                getTableRow().setStyle("-fx-background-color: #b6e1fc;");
            } else if ( ! isLockedProperty.get() && ! isSelected() ) {
//            } else if ( ! isLockedProperty.get() && ! selectedProperty().get() ) {
                getTableRow().setStyle(null);
            } else {
                throw new AssertionError("how did I get here?");
            }
        }

    }

}

如果字典大小相等,则更加简单:

import csv
from itertools import zip_longest

e = {'Jay':10,'Ray':40}
c = {'Google':5000}

def writeData():
    with open('employee_file20.csv', mode='w') as csv_file:
        fieldnames = ['emp_name','age','company_name','size']
        writer = csv.writer(csv_file)
        writer.writerow(fieldnames)

        for employee, company in zip_longest(e.items(), c.items()):
            row = list(employee)
            row += list(company) if company is not None else ['', '']  # Write empty fields if no company

            writer.writerow(row)

writeData()

注意一点:如果您使用Python3,将对字典进行排序。 Python2中不是这种情况。因此,如果您使用Python2,则应使用collections.OrderedDict而不是标准字典。

答案 1 :(得分:0)

可能会有更多的pythonic解决方案,但我会做类似的事情:

我以前没有用过.csv编写器,所以我只是用逗号分隔了输出。

e = {'Jay':10,'Ray':40}
c = {'Google':5000}
dict_list = [e,c] # add more dicts here.
max_dict_size = max(len(d) for d in dict_list)
output = ""
# Add header information here.
for i in range(max_dict_size):
  for j in range(len(dict_list)):
    key, value = dict_list[j].popitem() if len(dict_list[j]) else ("","")
    output += f"{key},{value},"
  output += "\n"
# Now output should contain the full text of the .csv file
# Do file manipulation here.
# You could also do it after each row,
# Where I currently have the output += "\n"

编辑:多想一点,我发现了一些可能会完善这一点的东西。您可以先在每个字典上使用.key()函数将字典映射到键列表,然后将其附加到空列表中。

这样做的好处是您可以“前进”,而不必从后面弹出词典项。它也不会破坏字典。