2012-03-16 45 views
5

Intentando escribir una función para dos cadenas y devuelve los caracteres que se cruzan en el orden en que aparecen en la primera cadena.Python - Intersección de cadenas

Esto es lo que he intentado:

def strIntersection(str1, str2): 
    for i in str1: 
     str3 = '' 
     str3 = str3.join(i for i in str1 if i in str2 not in str3) 
    return str3 

str1 = 'asdfasdfasfd' 
str2 = 'qazwsxedc' 

strIntersection(str1,str2) 

=> 'asdasdasd' 

sin embargo que sólo quieren que los personajes que aparezcan intersección de una vez con el fin de la primera cadena es decir. 'asd'

¿Alguien puede ayudar?

que he encontrado algunos problemas similares en otros foros, pero las soluciones todos parecen implicar listas mientras que Me gustaría que mi salida sea una cadena

Respuesta

6

Comprobar si las ocurrencias a la inversa para obtener el orden bajo control, y no emite caracteres que ya ha emitido:

def strIntersection(s1, s2): 
    out = "" 
    for c in s1: 
    if c in s2 and not c in out: 
     out += c 
    return out 

Sure you co Lo reescribo como una lista de comprensión, pero me parece más fácil de entender.

Para los datos de prueba, obtenemos:

>>> strIntersection('asdfasdfasfd' , 'qazwsxedc') 
'asd' 
+0

Gracias! Ciertamente es más fácil de entender. Me doy cuenta ahora que lo estaba complicando al tratar de usar '' join() – bang

+0

''' .join' es idiomático y nada complicado. Sin embargo, usarlo en un bucle, pasa por alto el punto. En realidad, el for-loop en el código OP es completamente inútil; simplemente causa el trabajo real - 'str3 = str3.join (i para i en str1 si yo en str2 no en str3)' para realizarse múltiples veces, con el mismo resultado cada vez, y el resultado se descarta cada vez pero el último. –

+0

No se puede reescribir este algoritmo en particular para que sea una lista comprensiva, al menos no sin invocar algunas cosas indocumentadas muy dudosas, porque el paso de filtrado 'c en s2 yc no en out' depende de los resultados parciales hasta este punto , que no son accesibles (excepto a través de cosas indocumentadas muy dudosas). –

7

¿Quieres una cadena formada por los caracteres únicos que son comunes a str1 y str2, en el orden en que aparecen en str1.

Unicidad y comunidad implican operaciones de conjunto: es decir, estamos buscando el conjunto de caracteres que aparecen en str1 y str2. Un conjunto está fundamentalmente desordenado, pero podemos reordenar los datos ordenando los caracteres de acuerdo con su "índice" de la primera aparición en str1. Entonces, es una simple cuestión de crear una secuencia a partir de la secuencia ordenada.

Poniendo todo junto, obtenemos:

''.join(sorted(set(str1) & set(str2), key = str1.index)) 
0

Parece que tu script actual debería hacerlo si se fija el error tipográfico en la cuarta línea:

str3 = str3.join(i for i in str1 if i in str2 not in str3) 

debe ser

str3 = str3.join(i for i in str1 if i in str2 and i not in str3) 

No recomendaría usar un juego para este simpy porque no garantizan el orden. Tu script también es más rápido.

+0

Estoy bastante seguro de lo que OP realmente quería decir era '(i para i en str1 si yo en str2 y no en str3)'. Excepto que esto no funciona porque aún no se ha construido el 'str3' con el que se debe comparar. Tiene su lógica confundida al intentar usar tanto el bucle for como la comprensión. En cuanto al rendimiento, ciertamente esperaría que los enfoques basados ​​en "conjuntos" sean mucho más rápidos para cadenas largas. –

+0

@Karl: Sí, tienes razón, actualizaré mi respuesta. Pero comparar con str3 no debería ser un problema, ya que solo necesita verificar la parte que ya se ha construido. – aquavitae

+0

El problema es que 'str3' ** no es **" la parte que ya se ha construido ". O ejecuta este código en un bucle o no lo hace. Si no lo hace, entonces 'str3' dará un UnboundLocalError - está tratando de referirse a lo que está asignando. Si lo haces, entonces tener un 'join' y una comprensión no tiene sentido, ya que solo quieres considerar el personaje actual contra los personajes que se intersectan, no toda la cadena. –

0
def str_intersection(str1, str2): 
    common_letters = set(str1) & set(str2) 
    str3 = '' 
    for c in str1: 
     if (c in common_letters) and (c not in str3): 
      str3 += c 
    return str3 
1

fácil es utilizar conjuntos de pitón

>>> a='asdfasdfasfd' 
>>> b='qazwsxedc' 
>>> set(a).intersection(b) 
set(['a', 's', 'd']) 
+0

Esto replica las respuestas existentes y no proporciona la clasificación que OP requiere. –