Test d'intégrité
Plutôt qu'écrire un code pour chaque cas (car ceci déclenche une alerte rouge : ceci n'est plus de l'informatique, mais de la bricole), pourquoi ne pas tester que la donnée est un iterable contenant soit des entiers uniquement, soit des iterable de même nature uniquement ?
def all_iterint(element):
if isinstance(element, int): return True
try:
return all(all_iterint(e) for e in element)
except TypeError: # raised if element is not iterable
return False
# test cases
a = (2, 3, 4, 5)
b = ((2, 3),
(4, 7),
)
c = ((2, 3),
((4, 2), (7, 4)),
)
d = ((2, 3),
((4, 2.), (7, 4)),
)
print(all_iterint(a)) # True
print(all_iterint(b)) # True
print(all_iterint(c)) # True
print(all_iterint(d)) # False
Pour la réflexion de fond : une fonction qui prévois plusieurs représentations d'une même donnée, c'est une marque de mauvaise conception. Et si c'est effectivement juste pour t’aménager une zone de confort, non seulement c'est inutile (un peu de rigueur, que diable !), mais c'est aussi que tu va avoir plusieurs utilisations différentes d'une même fonction.
Cette fonction sera probablement inutilement complexe.
Ensuite, il convient de vérifier que tu ais bien besoin de checker le type de ces données.
Parce que python est implémenté avec la notion de duck typing en tête, les données sont considérées selon ce qu'elles font, et non ce qu'elles sont.
Pourquoi ne pas opérer les traitements sur les données directement, et, si ça plante, afficher les données après coups et indiquer la source de l'erreur ?
Conversion de type hétérogènes vers type prédéfini
Le principe serais de convertir "tout type de données hétérogène" vers un type particuliers.
Ici, n'importe quelle composition de liste de données hétérogène et d'entier fait affaire de données hétérogènes, et une double liste d'entier le type ciblé.
1. Bonne chance
Ceci est un sujet de recherche assez ouvert, si mes souvenirs sont bons, et pas mal utilisé en robotique : la fusion de données hétérogènes. C'est beaucoup de maths.
Et cela nécessite d'avoir une compréhension profonde du sens des données hétérogènes utilisées.
2. Sans plus d'information, il est impossible de savoir quoi faire dans beaucoup de cas
Voici un jeu de données correspondant à la définition initiale :
data = [
[1, 2, [31, 32, [331, 332, 333], 34], 4],
5,
[61, [621], [71, [[7211], [7221]], 73], [81, 82, [831, 832]], 9],
]
Il est possible de convertir data de telle manière d'avoir un tableau à deux dimensions, mais cela de plusieurs manières. Très nombreuses en fait.
Une solution simple serais de collecter tous les entiers, et de constituer un tableau d'entier à deux dimensions en essayant d'optimiser la taille des colonnes, de manière à ce que la dernière ligne ai le minimum de "trou" possible :
[ # 4 éléments par ligne, sauf la dernière
[ 1, 2, 31, 32],
[331, 332, 333, 34],
[ 4, 5, 61, 621],
[ 71,7211,7221, 73],
[ 81, 82, 831, 832],
[9],
]
# NB: avec 3 éléments par lignes, il n'y aurais pas de trous
Mais bien sûr, il existe bien d'autres manière de faire. Il manque juste des spécifications sur le sens des données d'entrées. (voir la réflexion ci-dessus)
3. Implémentation d'un cas qui pourrait être utile
Considérons que les données d'entrées consiste en une liste d'éléments, de telle manière que tout élément est soit une liste d'entier, soit un entier.
Exemple :
[
[1, 2, 3],
4,
[5, 6],
[7]
]
L'objectif est alors de modifier les données jusqu'à se retrouver avec l'équivalent d'une matrice où tout élément non définit par les données initiales serais égales à zéro.
Dans l'exemple, nous obtiendrions :
[
[1, 2, 3],
[4, 0, 0],
[5, 6, 0],
[7, 0, 0]
]
Le code python permettant de passer ainsi de l'un à l'autre est :
def conv(data):
# tout élément de data doit être une liste
ldata = [e if isinstance(e, list) else [e] for e in data]
# obtention de la taille de la plus grande ligne
maxlen = max(len(l) for l in ldata)
# pour chaque ligne ajouter les zéros manquants
for line in ldata:
while len(line) < maxlen: line.append(0)
return ldata