Itertools Groupby дает неожиданный результат

#python #itertools

#python #python-itertools

Вопрос:

У меня есть два списка

скажем

 finalblobfpost1=['ABC/XYZ/16082020/K1_SS_ALM_222222_14082020.txt','ABC/XYZ/16082020/K1_SS_ALM_111111_14082020.txt','ABC/XYZ/15082020/K1_AB_KIL_444444_15082020.txt','ABC/XYZ/15082020/K1_AB_KIL_333333_15082020.txt']
  

С теми же датами для «K1_SS_ALM»

 finalblobfpost2=['ABC/XYZ/15082020/K1_SS_ALM_222222_15082020.txt','ABC/XYZ/16082020/K1_SS_ALM_111111_16082020.txt','ABC/XYZ/15082020/K1_AB_KIL_444444_15082020.txt','ABC/XYZ/16082020/K1_AB_KIL_333333_16082020.txt']
  

С разными датами из «K1_SS_ALM»

мне нужно сгруппировать с помощью K1_SS_ALM и K1_AB_KIL (re.findall(«w /w / d /(.*?)_d _d .txt «, текст))

Мой код пока:

 finalblobfpost1=['ABC/XYZ/16082020/K1_SS_ALM_222222_14082020.txt','ABC/XYZ/16082020/K1_SS_ALM_111111_14082020.txt','ABC/XYZ/15082020/K1_AB_KIL_444444_15082020.txt','ABC/XYZ/15082020/K1_AB_KIL_333333_15082020.txt']
keyf = lambda text: (re.findall("w /w /d /(.*?)_d _d .txt", text)  [text])[0].strip()
h=[list(items) for gr, items in groupby(sorted(finalblobfpost1), key=keyf)]
print(h)
  

Результат -Достаточно-хороший-ожидаемый

 [['ABC/XYZ/15082020/K1_AB_KIL_333333_15082020.txt', 'ABC/XYZ/15082020/K1_AB_KIL_444444_15082020.txt'], ['ABC/XYZ/16082020/K1_SS_ALM_111111_14082020.txt',
'ABC/XYZ/16082020/K1_SS_ALM_222222_14082020.txt']]
  

Код: 2

 finalblobfpost2=['ABC/XYZ/15082020/K1_SS_ALM_222222_15082020.txt','ABC/XYZ/16082020/K1_SS_ALM_111111_16082020.txt','ABC/XYZ/15082020/K1_AB_KIL_444444_15082020.txt','ABC/XYZ/16082020/K1_AB_KIL_333333_16082020.txt']
keyf1 = lambda text: (re.findall("w /w /d /(.*?)_d _d .txt", text)  [text])[0].strip()
h1=[list(items) for gr, items in groupby(sorted(finalblobfpost2), key=keyf1)]
print(h1)
  

результат таков: Не ожидается

 [['ABC/XYZ/15082020/K1_AB_KIL_444444_15082020.txt'], ['ABC/XYZ/15082020/K1_SS_ALM_222222_15082020.txt'], ['ABC/XYZ/16082020/K1_AB_KIL_333333_16082020.txt'], ['ABC/XYZ/16082020/K1_SS_ALM_111111_16082020.txt']]
  

Ожидаемый:

 [['ABC/XYZ/15082020/K1_AB_KIL_444444_15082020.txt','ABC/XYZ/16082020/K1_AB_KIL_333333_16082020.txt'],['ABC/XYZ/16082020/K1_SS_ALM_111111_16082020.txt','ABC/XYZ/15082020/K1_AB_KIL_444444_15082020.txt']]
  

Это не сгруппировало ключевые слова. Что-то не так с регулярным выражением или я делаю что-то не так?

Любезно сообщите, пожалуйста.

Ответ №1:

Ваш список должен быть отсортирован с помощью той же ключевой функции, которая используется в groupby!

попробуйте это:

 h1=[list(items) for gr, items in groupby(sorted(finalblobfpost2, key=keyf1), key=keyf1)]
  

Единственное отличие заключается в key=keyf1 вызове sorted

Вывод (такой же, как ожидалось):

 [['ABC/XYZ/15082020/K1_AB_KIL_444444_15082020.txt', 'ABC/XYZ/16082020/K1_AB_KIL_333333_16082020.txt'], ['ABC/XYZ/15082020/K1_SS_ALM_222222_15082020.txt', 'ABC/XYZ/16082020/K1_SS_ALM_111111_16082020.txt']]
  

Это явно написано в документах для groupby :

Операция groupby() аналогична фильтру uniq в Unix. Он генерирует разрыв или новую группу каждый раз, когда изменяется значение ключевой функции (именно поэтому обычно необходимо отсортировать данные с использованием одной и той же ключевой функции).

Комментарии:

1. Хорошо, тогда почему для первого списка все работало нормально?

2. @user11646543 из-за того, что часть datestamp после ABC/XYZ/ была упорядочена так же, как сортировка по ключевой функции, случайно…

3. @user11646543 если вы сомневаетесь в этом, посмотрите мою правку со ссылкой на документы…

Ответ №2:

попробуйте это,

Regex Demo

 import re
from itertools import groupby

print(
    [list(v) for _, v in groupby(finalblobfpost1,
                                 key=lambda x: re.search("wd _w{2}_w{3}", x).group())]
)
  

 [['ABC/XYZ/16082020/K1_SS_ALM_222222_14082020.txt', 'ABC/XYZ/16082020/K1_SS_ALM_111111_14082020.txt'], ['ABC/XYZ/15082020/K1_AB_KIL_444444_15082020.txt', 'ABC/XYZ/15082020/K1_AB_KIL_333333_15082020.txt']]
  

Комментарии:

1. Это работает, но не каждый раз, когда w {3} не приходит его динамика, которую я пробовал w insted w{3}. Это не работает. Можете ли вы предложить мне динамичный способ?

2. вы могли бы использовать wd _w{2}_[A-Za-z]{3,} который соответствует любому символу слова с длиной len, большей или равной 3.

3. Идеально!! Не могли бы вы, пожалуйста, сообщить мне, почему мой код не работал? Из-за? просто любопытно.