Чтобы сделать эти методы быстрее - PullRequest
0 голосов
/ 10 июня 2019

Я написал эту функцию в Python 3 для объединения двух XML-файлов.

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

Это функция:

def combine_element(one, other):
    channel_ids = []
    programs_startstop = []

    for el in one:
        if el.tag == 'channel':
            channel_ids.append(el.get('id'))
        elif el.tag == 'programme':
            programs_startstop.append((el.get('start'), el.get('stop')))

    i = 0
    printProgressBar(i, len(other), prefix = 'Progress:', suffix = 'Complete', length = 50)
    for el in other:
        if el.tag == 'channel':
            if not el.get('id') in channel_ids:
                one.append(el)
                channel_ids.append(el.get('id'))
        elif el.tag == 'programme':
            if not (el.get('start'), el.get('stop')) in programs_startstop:
                one.append(el)
                programs_startstop.append((el.get('start'), el.get('stop')))
        i += 1
        printProgressBar(i, len(other), prefix = 'Progress:', suffix = 'Complete', length = 50)

Это пример XML-файлов для слияния:

Первый файл:

<tv>
 <channel id="C1">
  <display-name lang="en">C1</display-name>
 </channel>
 <channel id="C2">
  <display-name lang="en">C2</display-name>
 </channel>
 <programme channel="C1" start="20190607040000 +0000" stop="20190607043000 +0000">
  <title lang="en">P1</title>
  <desc lang="en">Program 1</desc>
 </programme>
 <programme channel="C2" start="20190707040000 +0000" stop="20190707043000 +0000">
  <title lang="en">P2</title>
  <desc lang="en">Program 2</desc>
 </programme>
</tv>

Второйfile:

<tv>
 <channel id="C3">
  <display-name lang="en">C3</display-name>
 </channel>
 <channel id="C4">
  <display-name lang="en">C4</display-name>
 </channel>
 <programme channel="C3" start="20190607070000 +0000" stop="20190607073000 +0000">
  <title lang="en">P3</title>
  <desc lang="en">Program 3</desc>
 </programme>
 <programme channel="C4" start="20190707050000 +0000" stop="20190707063000 +0000">
  <title lang="en">P4</title>
  <desc lang="en">Program 2</desc>
 </programme>
</tv>

Предполагается, что код игнорирует элемент во втором файле, если он имеет тот же идентификатор, и игнорирует программу во втором файле, если он имеет одинаковое время запуска и остановки в первом файле.Приведенный здесь код xml является примером, потому что я не могу поделиться фактическими данными.

Это ожидаемый результат метода, но быстрее:

<tv>
<channel id="C1">
  <display-name lang="en">C1</display-name>
 </channel>
 <channel id="C2">
  <display-name lang="en">C2</display-name>
 </channel>
<programme channel="C1" start="20190607040000 +0000" stop="20190607043000 +0000">
  <title lang="en">P1</title>
  <desc lang="en">Program 1</desc>
 </programme>
 <programme channel="C2" start="20190707040000 +0000" stop="20190707043000 +0000">
  <title lang="en">P2</title>
  <desc lang="en">Program 2</desc>
 </programme>
 <channel id="C3">
  <display-name lang="en">C3</display-name>
 </channel>
 <channel id="C4">
  <display-name lang="en">C4</display-name>
 </channel>
 <programme channel="C3" start="20190607070000 +0000" stop="20190607073000 +0000">
  <title lang="en">P3</title>
  <desc lang="en">Program 3</desc>
 </programme>
 <programme channel="C4" start="20190707050000 +0000" stop="20190707063000 +0000">
  <title lang="en">P4</title>
  <desc lang="en">Program 2</desc>
 </programme>
</tv>

1 Ответ

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

Вы должны извлечь, где вы извлекаете элементы, в функцию генератора, которая выдает пару кортеж ключ-значение.

Создание словарей по результатам вызова функции генератора для обоих аргументов и объединение словаря.

def elements(lst):
    for el in lst:
        if el.tag == 'channel':
            yield el.get('id'), el
        if el.tag == 'programme':
            yield (el.get('start'), el.get('stop')), el

def combine_element(one, other):
    one_els = elements(one)
    other_els = elements(other)

    merged_els = dict(other_els)
    merged_els.update(one_els)

    result_els = []
    progressend = len(merged_els)
    for i, (_k, el) in enumerate(merged_els.items()):
        printProgressBar(
            i, progressend, prefix='Progress:', suffix='Complete', length=50)
        result_els.append(el)

    return result_els
...