Перебор списка, повторное использование определенных значений несколько раз в CSV - PullRequest
0 голосов
/ 04 июня 2019

У меня есть некоторые данные, которые выглядят так:

description "export"
source "factory1"
source "factory2"
source "factory3"
destination "customer1"
destination "customer2"
shipdate "asap"

description "export"
source "factory4"
source "factory5"
source "factory6"
destination "customer1"
shipdate "30"

Я сейчас пытаюсь создать CSV-файл, где он выглядит примерно так:

description,source,destination,shipdate
export,factory1,customer1,asap
export,factory2,customer1,asap
export,factory3,customer1,asap
export,factory1,customer2,asap
export,factory2,customer2,asap
export,factory3,customer2,asap
export,factory1,customer1,asap
export,factory2,customer1,asap
export,factory3,customer1,asap
export,factory4,customer1,30
export,factory5,customer1,30
export,factory6,customer1,30

Блоки данных передаются мне в виде списков Python, поэтому в настоящее время я перебираю их в виде и затем на основе первого слова помещаю их в другие списки. Однако, вероятно, есть гораздо более простой способ справиться с этим.

Пока мой код выглядит примерно так, но, как вы видите, это не решит мою проблему:

sourcelist = []
destlist = []
for item in list:
  if "source" in item:
    sourcelist.append(item)
  if "destination" in item:
    destlist.append(item)

Благодарен за любую помощь! Даже если это означает, что мне нужно переписать код!

Ответы [ 2 ]

1 голос
/ 04 июня 2019

Поскольку каждой отдельной строки недостаточно, данные должны быть собраны.Согласно вашему описанию и образцу, вы можете сделать это по блокам.Просто накапливайте все поля блока - уникальные поля будут содержать только один элемент.

Вы эффективно разбираете блоки с помощью генератора:

def parse_blocks(source: 'Iterable[str]'):
    block = {}
    for line in source:
        if not line:  # delimiter between blocks
            yield block
            block = {}
        else:
            key, value = line.split()
            block.setdefault(key, []).append(value.strip('"'))
    if block:
        yield block

Это дает вамитерируемый из блоков, такой как

{'description': ['export'], 'source': ['factory1', 'factory2', 'factory3'], 'destination': ['customer1', 'customer2'], 'shipdate': ['asap']}, ...

Для каждого блока вам нужны все комбинации по полям.itertools.product предоставляет это из коробки.

import itertools

def merge_lines(blocks: 'Dict[str, List[str]]', *fields: 'str'):
    for block in blocks:
        yield from itertools.product(
            *(block[key] for key in fields)
        )

Это предоставляет данные отдельных строк в виде повторяющихся наборов:

('export', 'factory1', 'customer1', 'asap'), ('export', 'factory1', 'customer2', 'asap'), ...

Вы можетепередать это непосредственно в csv или обработать его так, как вы считаете нужным.

import csv
import sys

fields = 'description', 'source', 'destination', 'shipdate'

writer = csv.writer(sys.stdout)  # or write to a file, pipe, ...
writer.writerow(fields)
for data in merge_lines(parse_blocks(input_list), *fields):  # insert your input here
    writer.writerow(data)

Это даст желаемый вывод в формате csv:

description,source,destination,shipdate
export,factory1,customer1,asap
export,factory1,customer2,asap
export,factory2,customer1,asap
export,factory2,customer2,asap
export,factory3,customer1,asap
export,factory3,customer2,asap
export,factory4,customer1,30
export,factory5,customer1,30
export,factory6,customer1,30
0 голосов
/ 04 июня 2019

Вот, пожалуйста,

import pandas as pd
import re
import itertools

# setup test data
raw_data_1 = ['description export', 'source factory 1', 'source factory 2', 'source factory 3', 'destination customer 1',
  'destination customer 2', 'shipdate asap']

raw_data_2 = ['description export', 'source factory 4', 'source factory 5', 'source factory 6', 'destination customer 1',
   'shipdate 30']

# create list of input data
data_list = [raw_data_1, raw_data_2]


# collect data from string
collected_data = []
for item in data_list:
    description = 0
    source_data = []
    destination_data = []
    ship_date = 0
    for data in item:
        if 'description' in data:
            description = re.sub('description ', '', data)
        elif 'source' in data:
            source = re.sub('source ', '', data)
            source_data.append(source)
        elif 'destination' in data:
            destination = re.sub('destination ', '', data)
            destination_data.append(destination)
        elif 'shipdate' in data:
            ship_date = re.sub('shipdate ', '', data)

    # create combinations
    combination_data = list(itertools.product(source_data, destination_data))

    # extend combinations data
    for item in combination_data:
        out = [description] + list(item) + [ship_date]
        collected_data.append(out)


# past data into data frame
data = pd.DataFrame(collected_data, columns=['description', 'source', 'destination','shipdate'])

# save data to file
data.to_csv('data.csv', index=False)

Вывод:

  description     source destination shipdate
0      export  factory 1  customer 1     asap
1      export  factory 1  customer 2     asap
2      export  factory 2  customer 1     asap
3      export  factory 2  customer 2     asap
4      export  factory 3  customer 1     asap
5      export  factory 3  customer 2     asap
6      export  factory 4  customer 1       30
7      export  factory 5  customer 1       30
8      export  factory 6  customer 1       30
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...