Як зрабіць наступную аперацыю ў пітонаў ў складаным шляху?

У мяне ёсць спіс картэжаў наступным чынам

[(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]

Цяпер мне трэба нешта накшталт гэтага

    <�Літый> У прыведзеным вышэй спісе, кожны элемент картэжа і першы элемент у картэж з'яўляецца індэксам, а другі элемент ўяўляе сабой значэнне.
  1. Мы павінны памножыць ўсе значэння картэжа, чые індэксы роўныя, а затым дадаць ўсе вынік множання для ўсіх індэксаў.
  2. Калі ёсць толькі адзін раз картэж з вызначаным індэксам, мы павінны зрабіць вынік множання нуль для гэтага. Гэта азначае, што картэж робіць не спрыяе канчатковай сумы.

Я б так моцна абавязаным, калі хто-небудзь можа мне дапамагчы. Я пачатковец у Python, так што знайсці яго цяжка.

1

7 адказы

Вось адзін са спосабаў зрабіць гэта. Выкарыстоўвайце itertools.groupby , каб стварыць групы, якія адпавядаюць кожны індэкс, памнажаць і дадаць

from operator import itemgetter, mul
from itertools import groupby
z = [(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]
z = sorted(z, key=itemgetter(0))
z = groupby(z, key=itemgetter(0))
z = ((key, list(value for (key, value) in groups)) for (key, groups) in z)
z = ((key, reduce(mul, values, 1)) for (key, values) in z if len(values) > 1)
z = sum(value for (key, value) in z)
print z
7425
3
дададзена
@ MikeMüller, добрая кропка :-). Аднак, прамежкавая друк заўчасна высільвае выразы генератара, што гэта рашэнне заснавана на.
дададзена аўтар iruvar, крыніца
Паказаны прамежкавага выніку мае выхаваўчае значэнне. ;)
дададзена аўтар Mike Müller, крыніца
Канешне. Пачынаючы з GroupBy , вы павінны зрабіць усё крокі зноў пасля друку.
дададзена аўтар Mike Müller, крыніца
Дададзены падрабязны варыянт гэтага рашэння. Гэта працуе, але варта. :)
дададзена аўтар Mike Müller, крыніца

Перанясіце ўсе картэжы ў Слоўнік, дзе ключы з'яўляюцца першымі элементамі і значэннямі з'яўляюцца спісамі другое элементаў. Фільтр Dict для значэнняў, якія маюць больш аднаго элемента. Выкарыстоўвайце паменшыць() памнажаць элементы кожнага значэння разам, і сума() , каб дадаць ўсе прадукты разам.

1
дададзена

Так што ўсё ўжо размешчаны рашэнні са ўбудаванымі функцыямі, але гэта не так шмат дадатковых, каб напісаць цыкл, які праходзіць праз і робіць тое, што вам трэба!

>>> l = [(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]
>>> hold = []
>>> for i in range(min(l)[0],max(l)[0] + 1):
...     hold2 = []
...     mult = 1
...     for t in l:
...             if t[0] == i:
...                     hold2.append(t[1])
...                     mult *= t[1]
...     if len(hold2) > 1:
...             hold.append(mult)
... 
>>> sum(hold)
7425

вы ўсталюеце адзін масіў для праверкі, колькі кожнага індэкса ёсць і проста перабіраць розныя індэксы і трымаць на памнажаючы наступнага нумара з індэксам адпаведнасці!

Акрамя таго, гэта будзе самая хуткая версія, якую вы атрымаеце. Проста таму, што яна не імпартуе нічога і не трэба ўзяць час, каб зрабіць гэта. Кожная версія, якую вы атрымалі на працягу секунды, але мне было сумна, таму я прымеркаваная іх усё:

Mine: 0:00:00.000477

1_CR: 00:00.073498

RedBaron: 0:00:00.079276
0
дададзена

Адказ вышэй з'яўляецца вялікім, але не так лёгка зразумець. На жаль, друк аднаго з г у чытаны спіс пачынаючы пасля GroupBy будзе спажываць итератор, як паказваў 1_CR. Вось рашэнне яшчэ раз, але з раздрукоўкамі прамежкавых крокаў. Лагічна ўсе этапы, пачынаючы з z3 павінен быць паўторна зроблена пасля кожнай друку.

from operator import itemgetter, mul
from itertools import groupby
from functools import reduce
import copy

z1 = [(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]
print('data:   ', z1)
z2 = sorted(z1, key=itemgetter(0))
print('sorted: ', z2)
z3 = groupby(z2, key=itemgetter(0))
print('grouped:', [(x, list(y)) for x,y  in z3])
z3 = groupby(z2, key=itemgetter(0))
z4 = ((key, list(value for (key, value) in groups)) for (key, groups) in z3)
print('lumped: ', list(z4))
z3 = groupby(z2, key=itemgetter(0))
z4 = ((key, list(value for (key, value) in groups)) for (key, groups) in z3)
z5 = ((key, reduce(mul, values, 1)) for (key, values) in z4 if len(values) > 1)
print('reduced:', list(z5))
z3 = groupby(z2, key=itemgetter(0))
z4 = ((key, list(value for (key, value) in groups)) for (key, groups) in z3)
z5 = ((key, reduce(mul, values, 1)) for (key, values) in z4 if len(values) > 1)
z6 = sum(value for (key, value) in z5)
print('sum:    ', z6)

І гэта ўзнагарода за ўсё гэта. Я думаю, што гэта сапраўды дапамагае зразумець, што адбываецца. Функцыянальнае праграмаванне можа быць цікава, калі вы разумееце, што адбываецца.

data:    [(1, 4), (3, 5), (2, 9), (6, 23), (3, 21), (2, 66), (5, 20), (1, 33), (3, 55), (1, 8)]
sorted:  [(1, 4), (1, 33), (1, 8), (2, 9), (2, 66), (3, 5), (3, 21), (3, 55), (5, 20), (6, 23)]
grouped: [(1, [(1, 4), (1, 33), (1, 8)]), (2, [(2, 9), (2, 66)]), (3, [(3, 5), (3, 21), (3, 55)]), (5, [(5, 20)]), (6, [(6, 23)])]
lumped:  [(1, [4, 33, 8]), (2, [9, 66]), (3, [5, 21, 55]), (5, [20]), (6, [23])]
reduced: [(1, 1056), (2, 594), (3, 5775)]
sum:     7425
0
дададзена

Вось просты працэдурны варыянт:

tups=[(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]

di={}
for t in tups:
    di.setdefault(t[0],[]).append(t[1])

ans=0
for k in di:
    if len(di[k])==1: continue
    x=1
    for e in di[k]: x*=e
    ans+=x

print ans  

друк 7425

Калі вы хочаце кароткі працэдурнай версіі:

di={}
for t in tups:
    di.setdefault(t[0],[]).append(t[1])
print sum(reduce(lambda x,y: x*y,l) for l in di.values() if len(l)>1)

А вось складана версія (ад ваўка):

di={}
{di.setdefault(t[0],[]).append(t[1]) for t in tups}
print sum(reduce(lambda x,y: x*y,l) for l in di.values() if len(l)>1)
0
дададзена

Вось адказ, які выкарыстоўвае слоўнікі:

def calculate(t):
    t1 = {}    # first time we encounter an index
    t2 = {}    # product of values
    for index, value in t:
        if index in t1:    # we have seen this index already
            if index not in t2:    # start the multiplier
                t2[index] = t1[index]
            t2[index] *= value     # chain multiplication
        else:
            t1[index] = value      # first time for this index
    return sum(t2.values())    # sum of multipliers
0
дададзена

Іншы (slighlty разные) спосаб. Мы збіраем элементы ў слоўнік, дзе кожны значэнне гэта слоўнік

import operator,collections
s=[(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]
s_d = collections.defaultdict(list)
for x in s: 
    s_d[x[0]].append(x[1])

S_d зараз

>>> s_d
defaultdict(, {1: [4, 33, 8], 2: [9, 66], 3: [5, 21, 55], 5: [20], 6: [23]})

Зараз для кожнага ключа, мы памнажаем значэнне, калі даўжыня значэнняў слоўніка больш за 1 яшчэ возвращать-

>>>map(lambda y: reduce(operator.mul,y[1],0) if len(y[1])>1 else 0,s_d.items())
[1056, 594, 5775, 0, 0]

Але вы хочаце суму, таму мы падводзім яго

>>>sum(map(lambda y: reduce(operator.mul,y[1],1) if len(y[1])>1 else 0,s_d.items()))
7425
0
дададзена