2010-10-28 4 views
-8

Je ne veux pas utiliser while ou for loops, je veux juste utiliser récursion pour retourner les nombres impairs dans une liste donnée. Merci!Comment puis-je retourner les nombres impairs d'une liste, en utilisant seulement la récursivité en Python?

+0

@ utilisateur481083: Ah! vous devriez toujours le dire. – pyfunc

+3

@ user481083: Suppression de ma réponse comme vous le souhaitez récursion et la réponse est fournie par GWW. Je ne suis pas sûr, pourquoi j'ai été upvoted pour ma réponse. +1 à GWW – pyfunc

+11

-1 @ zéro-effort "fais mes devoirs pour moi afin que je puisse éviter l'inconvénient d'apprendre quoi que ce soit" –

Répondre

8
def find_odds(numbers): 
    if not numbers: 
    return [] 
    if numbers[0] % 2 == 1: 
    return [numbers[0]] + find_odds(numbers[1:]) 
    return find_odds(numbers[1:]) 

Aucune des variables supplémentaires ou des paramètres nécessaires.

+0

C'est (IMNSHO) le meilleur solution à ce jour car elle minimise les arguments passés et n'endommage pas la liste originale. +1 – paxdiablo

+0

@pax, j'ai une question stupide à poser ... une nouvelle liste n'est-elle pas créée à chaque fois '[nombres [0]] + find_odds (nombres [1:])' est exécuté? : - \ @Josh, +1 – st0le

+0

@ st0le, cette ligne crée en réalité deux listes, une avec le premier élément, et une avec tous les éléments restants. – jnnnnn

3
def find_odds(numbers, odds): 
    if len(numbers) == 0: 
     return 
    v = numbers.pop() 
    if v % 2 == 1: 
     odds.append(v) 
    find_odds(numbers, odds) 

odds = [] 
numbers = [1,2,3,4,5,6,7] 
find_odds(numbers,odds) 
# Now odds has the odd numbers 
print odds 

est ici une sortie de test de ce que je reçois quand je lance ce

[7, 5, 3, 1]

+0

Où la liste des cotes est-elle retournée? – zallarak

+0

Les cotes variables J'ai édité ma réponse pour aider un peu – GWW

+1

Il est modifié par [référence] (http://en.wikipedia.org/wiki/Reference_%28computer_science%29). Donc vous appelez la fonction comme '' result = []; find_odds (nums, result) '' –

1
odds = [] 
def findOdds(listOfNumbers): 
    if listOfNumbers[0] % 2 == 1: 
     odds.append(listOfNumbers[0]) 
    if len(listOfNumbers) > 1: 
     findOdds(listOfNumbers[1:]) 

findOdds(range(0,10)) 
print odds 
# returns [1,3,5,7,9] 
+0

Qu'en est-il de la récursivité? –

+0

Ceci est clairement une solution supérieure à la récursivité. –

+0

Ainsi, quand votre client vous demande une application Web pour s'exécuter sous IIS (une exigence très spécifique), que pensez-vous qu'il dira quand vous livrerez une version de Websphere parce que c'est "clairement une solution supérieure"? :-) – paxdiablo

2

Voici une autre façon de le faire qui retourne la liste des nombres impairs plutôt que de modifier la liste transmise. Très similaire à celle fournie par GWW mais j'ai pensé que je l'ajouterais pour l'exhaustivité.

def find_odds(numbers, odds): 
    if len(numbers) == 0: 
     return odds 

    if numbers[0] % 2 == 1: 
     odds.append(numbers[0]) 

    return find_odds(numbers[1:],odds) 

print find_odds([1,2,3,4,5,6,7,8,9],[]) 

sortie est:

[1, 3, 5, 7, 9] 
+0

pouvez-vous penser à un moyen de le faire avec un seul paramètre? merci – zallarak

+3

Bien sûr, vous pourriez (dans un sens) créer la liste pour contenir _all_ l'information et juste passer la liste. Mais c'est une exigence encore pire que votre "tout aussi récursif", car il a été ajouté après la réponse à la question. Et, pour être honnête, je préfère aider les gens que de jouer à des jeux "changeons les exigences" - ce n'est pas comme si je n'en avais pas assez dans mon job _real_ :-) – paxdiablo

0
>>> def fodds(alist, odds=None): 
...  if odds is None: odds = [] 
...  if not alist: return odds 
...  x = alist[0] # doesn't destroy the input sequence 
...  if x % 2: odds.append(x) 
...  return fodds(alist[1:], odds) 
... 
>>> fodds(range(10)) # only one arg needs to be supplied 
[1, 3, 5, 7, 9] # same order as input 
>>> 

Celui-ci évite les frais généraux de la copie de la liste, au prix d'obtenir la réponse en arrière et une grande augmentation du facteur de la laideur:

>>> def fo(aseq, pos=None, odds=None): 
...  if odds is None: odds = [] 
...  if pos is None: pos = len(aseq) - 1 
...  if pos < 0: return odds 
...  x = aseq[pos] 
...  if x % 2: odds.append(x) 
...  return fo(aseq, pos - 1, odds) 
... 
>>> fo(range(10)) 
[9, 7, 5, 3, 1] 
>>> 
0
def odds(L): 
    if L == []: 
     return [] 
    else: 
     if L[0]%2: 
      B = odds(L[1:]) 
      B.append(L[0]) 
      return B 
     else: 
      return odds(L[1:]) 
3

Compte tenu de la limite de profondeur de la pile par défaut de 1000 en python, je n'utiliserais vraiment pas la récursivité pour ça. Je sais qu'il ya beaucoup d'implémentations récursives ci-dessus est donc ici un non récurrent qui fait les choses comme python:

print filter(lambda x: x % 2, range(0, 10)) 

Et pour être complet; Si vraiment vous devez vraiment utiliser la récursivité, voici ce que je vais faire. Ceci est très similaire à la version par Josh Matthews.

def rec_foo(list): 
    if not list: 
     return [] 
    return ([list[0]] if list[0] % 2 else []) + rec_foo(list[1:]) 

print rec_foo(range(1, 10)) 
+0

+1: le filtre semble être la façon pythonique. –

+3

Une méthode plus pythonique serait '[x pour x dans lst si x% 2]'. Et n'utilisez pas de noms intégrés (liste) comme noms de paramètres. – Rudi

+0

Eh bien, je vais admettre que l'utilisation de la liste n'était pas le meilleur choix, mais bon, nous faisons tous des erreurs. Ce que je ne comprendrai jamais, c'est comment une liste comp est plus pythonique qu'une fonction intégrée. – dcolish

7
def only_odd(L): 
    return L[0:L[0]&1]+only_odd(L[1:]) if L else L 

Cette version est beaucoup plus rapide car il évite de faire des copies de L

def only_odd_no_copy(L, i=0): 
    return L[i:i+(L[i]&1)]+only_odd_no_copy(L, i+1) if i<len(L) else [] 

Celui-ci utilise seulement O (log n) espace de pile

def only_odd_logn(L): 
    x=len(L)/2+1 
    return L[:L[0]&1] + only_odd2(L[1:x]) + only_odd_logn(L[x:]) if L else L 
+0

sympa! J'aime l'utilisation de & – dcolish

+0

@dcolish: 'some_int & 1' est juste une version obfusquée de' some_int% 2' ... qu'est-ce que c'est? C'est le L [0: booléen] c'est le coup de gnène ... +1 de moi. –

+0

Hmm ... Je dois avoir mis ce zéro là car explicite est mieux que implicite –

0

Eh bien, il sont un tas d'autres réponses, mais je pense que le mien est le plus propre:

def odds(L): 
    if not L: 
     return [] 
    return [L[0]] * (L[0] % 2) + odds(L[1:]) 

Exercice amusant mais juste pour réitérer, ne le faites jamais récursivement dans la pratique.

+0

la mutation de l'argument d'entrée à une liste vide est propre? –

0

bien puisque nous contribuons tous:

def odds(aList): 
    from operator import lshift as l 
    if aList and not aList[1:]: 
     return aList if aList[-1] - l(aList[0]>>1, 1) else list() 
    return odds(aList[:len(aList)/3+1]) + odds(aList          \ 
    [len(aList)/3+1:]) if aList else [] 
2

Comme il est parti, je ne pensais que je serais avec un carillon agréable, sensible, programmeur réel solution TM. Il est écrit en emacs et inspiré par la réponse de gnibbler.Comme le sien, il utilise &1 au lieu de % 2 (ajouter 2 dans co_consts est pure décadence si 1 est déjà là) et utilise cette astuce astucieuse pour obtenir le premier élément seulement si c'est impair, mais rase quelques cycles pour un gain de temps d'environ 5 % (sur ma machine, exécutant 2.6.5 compilé avec GCC 4.4.3 sur un noyau linux2).

from opcode import opmap 
import types 

opcodes = [opmap['LOAD_FAST'],  0,0, # L 
      opmap['JUMP_IF_FALSE'], 24,0, 
      opmap['DUP_TOP'], 
      opmap['LOAD_CONST'],  0,0, # 0 
      opmap['BINARY_SUBSCR'], 
      opmap['LOAD_CONST'],  1,0, # 1 
      opmap['BINARY_AND'], 
      opmap['SLICE+2'], 
      opmap['LOAD_GLOBAL'], 0,0, # odds 
      opmap['LOAD_FAST'],  0,0, 
      opmap['LOAD_CONST'],  1,0, 
      opmap['SLICE+1'], 
      opmap['CALL_FUNCTION'], 1,0, 
      opmap['BINARY_ADD'], 
      opmap['RETURN_VALUE']] 

code_str = ''.join(chr(byte) for byte in opcodes) 

code = types.CodeType(1, 1, 4, 0x1 | 0x2 | 0x40, code_str, (0, 1), 
         ('odds',), ('L',), '<nowhere>', 'odds', 
         0, '') 

odds = types.FunctionType(code, globals()) 
+0

+1, Aimerait voir le résultat de l'OP soumettant ceci pour leurs devoirs. J'ai ajouté quelques options améliorées à ma réponse –

+0

+1 pour le look wtf du prof – Scott

Questions connexes