Seite 1 von 1

Teiliste in Liste enthalten?

Verfasst: Freitag 3. März 2006, 10:50
von Mr_Snede
Ich möchte gerne überprüfen, ob eine Liste mit einer anderen Liste übereinstimmt, die unter Umständen mehr Einträge hat:

Leider geht es so nicht :-(

Code: Alles auswählen

>>> l1 = ["1","2","3","4"]
>>> l2 = ["2","3"]
>>> l2 in l1
False
Die Idee es so zu machen bekam ich aus dem Wiki:
http://wiki.python.de/Neue_Features?hig ... essertesIn

cu Sebastian

Re: Teiliste in Liste enthalten?

Verfasst: Freitag 3. März 2006, 11:00
von Francesco
Mr_Snede hat geschrieben:Ich möchte gerne überprüfen, ob eine Liste mit einer anderen Liste übereinstimmt, die unter Umständen mehr Einträge hat:

Leider geht es so nicht :-(

Code: Alles auswählen

>>> l1 = ["1","2","3","4"]
>>> l2 = ["2","3"]
>>> l2 in l1
False
Die Idee es so zu machen bekam ich aus dem Wiki:
http://wiki.python.de/Neue_Features?hig ... essertesIn

cu Sebastian
Das würde bedeuten:

>>> l1 = ["1","2","3",["2","3"],"4"]
>>> l2 in l1
True

Du suchst ein Liste als Listenelement in l1.

Verfasst: Freitag 3. März 2006, 11:05
von Mr_Snede
och menno,
warum muss denn das was ich nicht will auch noch logisch bzw sinnvoll sein? :evil:

Dann werde ich halt die größere Liste manuell erst zusammenstutzen.
Und mir später mal meine Datenstruktur überdenken.

Cu sebastian

Verfasst: Freitag 3. März 2006, 11:17
von Francesco
Mr_Snede hat geschrieben:och menno,
warum muss denn das was ich nicht will auch noch logisch bzw sinnvoll sein? :evil:

Dann werde ich halt die größere Liste manuell erst zusammenstutzen.
Und mir später mal meine Datenstruktur überdenken.

Cu sebastian
Ich finde das Problem interessant, weiss aber auch keine (einfache)
Lösung.

Intuitiv hätte ich das wahrscheinlich auch so probiert.

Verfasst: Freitag 3. März 2006, 11:18
von mitsuhiko
etwa sowas?

Code: Alles auswählen

set(l2).issubset(set(l1))

Verfasst: Freitag 3. März 2006, 11:25
von Francesco
blackbird hat geschrieben:etwa sowas?

Code: Alles auswählen

set(l2).issubset(set(l1))
Super, danke!
Wieder was neues gelernt, werde ich mir gleich notieren.

Trotzdem:
Bei strings geht es ja auch:
t = "teststring"
tsub= "estsr"

bei der Liste muessten die Argumente irgendwie nicht als Liste
übergeben werden können, sondern als Elemente,
dann könnte man es theoretisch auch so behandeln. :?

Verfasst: Freitag 3. März 2006, 11:43
von Mr_Snede
Danke schön.

nach ein wenig Doku[1] und Forum lesen sieht es bei mir nun so aus:

Code: Alles auswählen

Python 2.3.5 (#2, Nov 20 2005, 16:40:39)
[GCC 4.0.3 20051111 (prerelease) (Debian 4.0.2-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> l1 = ["1","2","3","4"]
>>> l2 = ["2","3"]
>>> l2 in l1
False
>>> import sets
>>> sets.Set(l2).issubset(sets.Set(l1))
True
cu Sebastian

[1] http://www.python.org/doc/2.3.5/lib/module-sets.html

Verfasst: Freitag 3. März 2006, 11:48
von modelnine
Du weisst, dass der Vergleich mit Strings nicht angebracht ist?

Denn:

Code: Alles auswählen

modelnine@phoenix ~ $ python
Python 2.4.2 (#1, Feb  5 2006, 17:30:13)
[GCC 4.0.2 (Gentoo 4.0.2-r3, pie-8.7.8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "hello" in "test hello 2"
True
>>> "hello" in "test heiko luft"
False
>>> set(["1","2"]).issubset(set(["1","2","3","4"]))
True
>>> set(["1","2"]).issubset(set(["2","3","1","4"]))
True
>>>
Wenn's Dir darum geht eine wirkliche "Unterliste" zu finden wie das str in str macht (und eben nicht nur zu gucken ob die Elemente aus der ersten Liste in der zweiten drin sind, unabhängig von der Ordnung), dann mußt Du's selbst implementieren.

Verfasst: Freitag 3. März 2006, 11:56
von Mr_Snede
In Worten lautet mein Problem:
Sind alle!! Elemente der kürzeren Liste in der Längeren enthalten?

So wie du es beschreibst und ich die Doku verstanden habe tun Sets genau das.

cu Sebastian

Verfasst: Freitag 3. März 2006, 12:21
von modelnine
Dein Problem mag es lösen, aber ich wollte darauf hinaus dass der Vergleich mit dem str in str nicht angebracht ist, weil der nicht prüft ob alle Elemente (also Zeichen) in dem anderen String vorhanden sind, sondern ob der Unterstrings s1 im String s2 vorhanden ist.

Ganz was anderes als zu Prüfen ob das eine eine Untermenge des anderen ist...

PS: Es war sogar nicht an Dich gerichtet, sondern an Franceso, der nämlich die str in str-Geschichten aufgebracht hat...

Verfasst: Freitag 3. März 2006, 19:07
von Mr_Snede
hmm irgendwo hapert es bei der Umsetzung von dem Beispiel für mein Programm.

Igendwie stehe ich mit der Fehlermeldung etwas sei nicht hashbar auf Kriegsfuß.

Gegeben ist (stark gekürzter Auszug):

Code: Alles auswählen

class  Konto:
      def  __init__(self):
         self.konto_liste = []

   def import_csv(self, Pfad_zum_neuen_csv):
      # eine neue csv Datei in konto_liste einlesen
      # vorhandene Eintraege werden uebergangen

      in_file=file(Pfad_zum_neuen_csv, 'r')
      reader=csv.reader(in_file,mydialect)

      #if not zeile[1:] in self.konto_liste:
      if not sets.Set(zeile[1:]).issubset(sets.Set(self.konto_liste)):
         elf.konto_liste.append(zeile)

Code: Alles auswählen

Traceback (most recent call last):
  File "konto-core-002.py", line 267, in ?
    k.test_import_csv()
  File "konto-core-002.py", line 230, in test_import_csv
    self.import_csv("test1.csv")
  File "konto-core-002.py", line 89, in import_csv
    if not sets.Set(zeile[1:]).issubset(sets.Set(self.konto_liste)):
  File "/usr/lib/python2.3/sets.py", line 429, in __init__
    self._update(iterable)
  File "/usr/lib/python2.3/sets.py", line 374, in _update
    data[element] = value
TypeError: list objects are unhashable
Kann es daran liegen, dass self.konto_liste zu diesem Zeitpunkt noch leer ist?

Verfasst: Freitag 3. März 2006, 20:30
von r2d2
warum iterierst du nicht einfach über die listen?

Code: Alles auswählen

mylist1 = ["1","2","3","4"]
mylist2 = ["2","3"]

for item in mylist2:
    if item in mylist1:
        print item," in mylist1"
    else:
        print item," nicht in mylist1"
r2d2

Verfasst: Freitag 3. März 2006, 23:18
von Mr_Snede
Danke dir für den Tipp,
ich werde jetzt erst einmal in meinen Programm etwas aufräumen und eine Nacht drüber schlafen.

cu Sebastian

Verfasst: Montag 6. März 2006, 00:40
von Mr_Snede
Hier das Ergebnis eines harten Wochenende - mann habe ich gekäpft, aber ganz alleine geschafft.
Ich bin richtig stolz auf mich :-)


Was sagt ihr dazu?
(Ich hoffe ihr findet den Quellcode zwischen den Konsoleausgaben.)

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# iteriere ueber 2 2dimensionale Liste

import pprint
pp = pprint.PrettyPrinter(indent=4)

'''
Problembeschreibung:
- ein Teilstück einer Zeile aus neue_liste  ist in einer Zeile von alte_liste enthalten:
-- False:
      Zeile wird an alte_liste angehängt
      und bekommt den Namen der Datei mit, aus der neue_liste importiert wurde.
-- True:
      in der übereinstimmenden Zeile wird der Name der Datei,
      aus der neue_liste importiert wurde, eingetragen

Die Dateinamen werden hier durch die Strings "d1" und "d2" simmuliert 
'''

alte_liste = [ ["01", "11",["d1"], "21_a"],
               ["02", "12",["d1"], "22_a"],
               ["03", "13",["d1"], "23_a"] ]

neue_liste = [ ["02", "12",[], "22_n"],
               ["03", "13",[], "23_n"],
               ["04", "14",[], "24_n"] ]


def schonenthalten(zeile_neue_liste, alte_liste):
   print "-->schonenthalten aufgerufen"
   print " ", zeile_neue_liste, "(neue)"
   print " ",alte_liste[0], "(alte)"

   for index, item2 in enumerate(alte_liste):
      print "index", index
      print "len(alte_liste)", len(alte_liste)
      if zeile_neue_liste[:1] == item2[:1]:
         print "schon enthalten"
         print " ", zeile_neue_liste, "(alte)"
         print " ", item2, "(neue)"
         return [True, index]
      else:
         print "nix gleich:"
         print " ", zeile_neue_liste, "(neue)"
         print " ", item2, "(alte)"
         #schonenthalten(zeile_alte_liste, neue_liste[1:])
   print "ende von alte_liste erreicht"
   return [False,]


temp_list = []

for i_neu, item_neu in enumerate(neue_liste):
   print "\n~~~~~~~~~~~~~~~~~~~~~~~~"
   print i_neu,".ter Durchlauf enumerate(neue_liste):"
   print "item_neu:\n ", item_neu, "\n"
   ergebnis = schonenthalten(item_neu, alte_liste)
   print "ergebnis ",ergebnis
   if ergebnis[0] == True:
      print "alte_liste, Spalte:", ergebnis[1]
      print "alte_liste:\n ", alte_liste[ergebnis[1]]
      alte_liste[ergebnis[1]][2].append("d2")
      print "alte_liste:\n ", alte_liste[ergebnis[1]]
   else:
      item_neu[2].append("d2")
      temp_list.append(item_neu)



print "\n-------------\n Ergebnis:\n-------------"

pp.pprint(alte_liste + temp_list)
Das Ergebnis sieht dann so aus:

Code: Alles auswählen

-------------
 Ergebnis:
-------------
[   ['01', '11', ['d1'], '21_a'],
    ['02', '12', ['d1', 'd2'], '22_a'],
    ['03', '13', ['d1', 'd2'], '23_a'],
    ['04', '14', ['d2'], '24_n']]

Verfasst: Montag 6. März 2006, 13:37
von Mr_Snede
habe grade beim Entfernen der print statements gesehen, dass ich einen kompletten "else Zweig" nicht brauche.

So sieht mein Prototyp also im Moment aus:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import pprint
pp = pprint.PrettyPrinter(indent=4)

alte_liste = [ ["01", "11",["d1"], "21_a"],
               ["02", "12",["d1"], "22_a"],
               ["03", "13",["d1"], "23_a"] ]

neue_liste = [ ["02", "12",[], "22_n"],
               ["03", "13",[], "23_n"],
               ["04", "14",[], "24_n"] ]


def schonenthalten(zeile_neue_liste, alte_liste):
   for index, item2 in enumerate(alte_liste):
      if zeile_neue_liste[:1] == item2[:1]:
         return [True, index]
   return [False,]

temp_list = []
for i_neu, item_neu in enumerate(neue_liste):
   ergebnis = schonenthalten(item_neu, alte_liste)
   if ergebnis[0] == True:
      alte_liste[ergebnis[1]][2].append("d2")
   else:
      item_neu[2].append("d2")
      temp_list.append(item_neu)

print "\n-------------\n Ergebnis:\n-------------"
pp.pprint(alte_liste + temp_list)