1
votes

Comment effectuer des opérations arithmétiques élémentaires (par exemple, ajouter, soustraire, multiplier) de deux listes de forme égale avec des imbrications arbitraires

Je souhaite effectuer des opérations mathématiques élémentaires (par exemple, somme, multiplication ..) sur deux listes Python contenant des nombres ou plusieurs listes imbriquées qui peuvent contenir à nouveau des nombres ou des listes et ainsi de suite.

Les formes des deux listes sont égaux lors de l'exécution de l'opération. De plus, le résultat doit être de la même forme que les deux listes d'entrée.

Une forme peut différer de:

  1. longueur ,

  2. largeur (c'est-à-dire le nombre d'imbrications),

  3. ordre (par exemple, les listes commencent par un nombre suivi d'une liste imbriquée, mais il se peut aussi qu'elle commence par une liste imbriquée, suivie de nombres).

La forme change de façon arbitraire chaque fois que je veux effectuer une opération mathématique.

Comment puis-je effectuer des opérations mathématiques sur des listes de forme arbitraire?

Dans le passé, J'ai implémenté un morceau de code personnalisé pour chaque forme différente, similaire à 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , mais je me demandais s'il existe déjà une solution plus générale sous la forme d'une bibliothèque ou d'un code de référence pour cela.

Exemple 1 (addition):

[[32, 6], 1, 9]

donnerait

g = [[4,2],1,1]
h = [[8,3],1,9]
i = elementwiseMUL(g,h)
i

Exemple 2 (addition):

[11, [22, 33], 44, [55, 66, 77], [[88], [99, 110]]]

donnerait

d = [ 1,[ 2, 3],  4, [ 5, 6, 7], [[ 8], [ 9, 10]]]
e = [10,[20,30], 40, [50,60,70], [[80], [90,100]]]
f = elementwiseSUM(d,e)
f

Exemple 3 ( multiplication):

[11, 22, 33, 44, [55, 66, 77, 88]]

donnerait

a = [ 1, 2, 3, 4,[ 5, 6, 7, 8]]
b = [10,20,30,40,[50,60,70,80]]
c = elementwiseSUM(a,b)
c

elementwiseSUM () et elementwiseMUL () sont des espaces réservés pour le li fonctions brary que je recherche.


2 commentaires

Comment gérez-vous la situation lorsque les formes ne sont pas les mêmes?


Les formes des deux listes sont toujours égales lors de l'exécution de l'opération arithmétique. scalaire unique.


4 Réponses :


0
votes

Il ne s'agit pas exactement de profiter d'un module python intégré (en plus de operator ), mais qu'en est-il de quelque chose comme ça?

[11, 22, 33, 44, [55, 66, 77, 88]]
[[32, 6], 1, 9]

Résultat: p >

def element_wise(list_a, list_b, operator):
    result = []
    assert len(list_a) == len(list_b)
    for a, b in zip(list_a, list_b):
        is_lists = isinstance(a, list) and isinstance(b, list)
        is_ints = isinstance(a, int) and isinstance(b, int)

        if is_lists:
            result.append(element_wise(a, b, operator))
        elif is_ints:
            result.append(operator(a, b))
        else:
            raise ValueError
    return result


def main():

    from operator import add, mul

    list_sum_a = [ 1,  2,  3,  4, [ 5,  6,  7,  8]]
    list_sum_b = [10, 20, 30, 40, [50, 60, 70, 80]]

    list_mul_a = [[4, 2], 1, 1]
    list_mul_b = [[8, 3], 1, 9]

    result_sum = element_wise(list_sum_a, list_sum_b, add)
    result_mul = element_wise(list_mul_a, list_mul_b, mul)

    print(result_sum)
    print(result_mul)

    return 0


if __name__ == "__main__":
    import sys
    sys.exit(main())


0 commentaires

2
votes

Voici la solution que j'ai trouvée avec

a = [ 1,  2,  3,  4, [ 5,  6,  7,  8]]
b = [10, 20, 30, 40, [50, 60, 70, 80]]

def element_wise(a, b, f):
    return [element_wise(i, j, f) if type(i) == list and type(j) == list else f(i, j) for i, j in zip(a, b)]

c = element_wise(a, b, lambda x, y: x + y) # [11, 22, 33, 44, [55, 66, 77, 88]]

donc a et b sont vos listes, et f code> est la fonction que vous voulez appliquer, comme vous pouvez le voir, j'ai écrit une fonction simple pour ajouter des entrées

Vous pouvez soit écrire vos propres lambdas, soit simplement utiliser le module operator .


2 commentaires

J'aime celui-ci car il est plus propre d'appeler la fonction + plus polyvalent avec lambda. Bien que le 'et' ne semble pas être nécessaire, (cochez une seule case) car il se cassera, peu importe si la liste est un format incorrect.


Vous avez tout à fait raison, je viens d'ajouter le et pour être vraiment complet :)



0
votes

Je ne suis pas sûr d'une bibliothèque qui a une méthode intégrée, mais en utiliser une ne serait pas plus rapide que d'en créer une vous-même

un exemple qui n'est pas un code de production mais qui montre Le moyen simple de le faire est:

import operator
ops = {
    "+": operator.add,
    "-": operator.sub,
    "*": operator.mul,
    "/": operator.div
}

a = [ 1,[ 2, 3],  4, [ 5, 6, 7], [[ 8], [ 9, 10]]]
b = [10,[20,30], 40, [50,60,70], [[80], [90,100]]]


def foo(x, y, op):
    if type(x) == list:
        return [foo(a, b, op) for a, b in zip(x, y)]
    else:
        return ops[op](x, y)

#Run
print foo(a, b, '+')


0 commentaires

0
votes

Je donne le code de solution par exemple un et trois, mais cette solution dépend totalement de votre liste, c'est-à-dire combien de liste vous avez dans la liste car j'utilise la boucle for et cela dépend de votre liste.

Exemple 1 (solution de sommation)

g = [[4,2],1,1]
h = [[8,3],1,9]
def elementwiseMUL(g, h):
    pl = []
    cl = []
    for i, j in zip(g, h):
        if type(i) and type(j) != list:
            cl.append(i*j)
        if type(i) and type(j) == list:
            for k, l in zip(i, j):
                pl.append(k*l)
    pl.append(cl)
    return pl
print(elementwiseMUL(g, h))

Exemple 2 (solution de multiplication)

a = [ 1, 2, 3, 4,[ 5, 6, 7, 8]]
b = [10,20,30,40,[50,60,70,80]]   
def elementwiseSUM(a, b):
    pl = []
    cl = []
    for i, j in zip(a, b):
        if type(i) and type(j) != list:
            pl.append(i+j)
        if type(i) and type(j) == list:
            for k, l in zip(i, j):
                cl.append(k+l)
    pl.append(cl)
    return pl
print(elementwiseSUM(a, b))


0 commentaires