背景
我有多个不同长度的字典。我需要将字典的值写入单个CSV文件。我想我可以逐个循环浏览每个字典,然后将数据写入CSV。我遇到了一个小型格式化问题。
问题/解决方案
我意识到在循环浏览第一个字典之后,第二次写作的数据被写入了第一个字典结束的行,如第一张图片中所示。我理想地希望我的数据按如下所示打印在第二张图片
中我的代码
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:我将有两个以上的词典,所以我正在寻找一种通用的方式,可以在所有词典的标题下从行打印数据。我愿意接受所有解决方案和建议。
答案 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()函数将字典映射到键列表,然后将其附加到空列表中。
这样做的好处是您可以“前进”,而不必从后面弹出词典项。它也不会破坏字典。