Komplexer Listen (String) Filter

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
wayne
User
Beiträge: 5
Registriert: Dienstag 16. April 2013, 21:35

Hi ich stehe vor einem Problem !!! :K Ich möchte diese Ausgabe filtern:

Und zwar möchte alle Nutzer die den Beziehungsstatus 1(TRUE) haben mit vornamen und namen ausgeben. Und mir fehlt absolut der Ansatz. hab mir schon unzählgie Tutorials dazu angeshen, aber bin zu keiner Lösung gekommen. Wäre sehr Dankbar für einen Vorschlag.

{u'p': n'schmitt', v'markus', u's': 1, u'w':hamburg'}, {u'p': n'schroeder', v'steffi', u's': 0, u'w':berlin'}, {u'p': n'meier', v'klaus', u's': 1, u'w':koeln'}, {u'p': n'bruns', v'dieter', u's': 0, u'w':berlin'},

p = profil
n = nachname
v = vorname
s = beziehungsstatus (1 steht für TRUE und 0 für FALSE)
w = wohnort

HIER NOCHMAL ZUR BESSEREN ÜBERSICHT DIE EINZELENEN PROFILE DIE ALLE IN EINR ZEILE STEHEN !!!

{u'p': n'schmitt', v'markus', u's': 1, u'w':hamburg'},

{u'p': n'schroeder', v'steffi', u's': 0, u'w':berlin'},

{u'p': n'meier', v'klaus', u's': 1, u'w':koeln'},

{u'p': n'bruns', v'dieter', u's': 0, u'w':berlin'},

#####################################################

If s ==1
print v,n

Ich muss jedes Profil das in Klammern steht {...} nach dem parameter 's' dursuchen. Wenn der Wert 1 (TRUE) ist sollen 'v' (vorname) und 'n' (nachname) in einer liste ausgegeben werden.


re.match
re.findall

Ich bin dankbar für jeden Lösungsansatz
BlackJack

@wayne: Was ist denn das für ein komisches Datenformat? Wo kommt das her? Sieht das wirklich *so* aus?
xeike
User
Beiträge: 83
Registriert: Donnerstag 28. Februar 2013, 09:58

Hi!
wayne hat geschrieben:Und zwar möchte alle Nutzer die den Beziehungsstatus 1(TRUE) haben mit vornamen und namen ausgeben. Und mir fehlt absolut der Ansatz. hab mir schon unzählgie Tutorials dazu angeshen, aber bin zu keiner Lösung gekommen. Wäre sehr Dankbar für einen Vorschlag.
Ich würde den String zerlegen mit re.search(), dann die einzelnen Teile durchsuchen und alles in eine vernünftige Datenstruktur überführen. Vielleicht ne Datenbank oder XML oder was auch immer.

Code: Alles auswählen

>>> s = "{u'p': n'schmitt', v'markus', u's': 1, u'w':hamburg'}"
>>> import re
>>> m = re.search("{u'p': n'(?P<nachname>.*?)'", s )
>>> m.group('nachname')
'schmitt'
>>> 
Hoffe, das hilft.

Xe
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Das Datenformat ist seltsam. Aber gut, gehen wir davon aus, dass es wirklich einen String gibt der so aussieht und auch immer diesen Aufbau hat.

Ich würde dann zuerst die einzelnen Elemente voneinander separieren. Als Trenner bietet sich da die Zeichenfolge }, an. Anschließend bemühen wir dann einen regulären Ausdruck um das jeweilige Element zu zerlegen.

Code: Alles auswählen

import re
data = "{u'p': n'schmitt', v'markus', u's': 1, u'w':hamburg'}, {u'p': n'schroeder', v'steffi', u's': 0, u'w':berlin'}, {u'p': n'meier', v'klaus', u's': 1, u'w':koeln'}, {u'p': n'bruns', v'dieter', u's': 0, u'w':berlin'}"

elements = data.split('}')

for element in filter(bool, elements):
    match = re.search(r":\sn'(.*?)'.*?v'(.*?)'.*'s': (\d)", element)
    if match.group(3) == '1':
        print('{vorname} {name}'.format(vorname=match.group(2), name=match.group(1)))
filter habe ich verwendet um das letzte leere Element erst gar nicht bearbeiten zu müssen.

Die Realisierung ist natürlich fragil. Änderungen in der Reihenfolge der Daten oder plötzlich neu auftauchende Leerzeichen können dazu führen, dass der reguläre Ausdruck nichts mehr findet.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Das ist schon ein sehr komisches Dateiformat. Es gibt Sonderzeichen {},:, Zahlen und Strings nicht durch ein Anfangs- aber nur durch ein End-Zeichen »'« gekennzeichnet sind. Dann gibt es noch Doppelstrings, die wohl so eine Art typisierter String sind.
Hier nun der Parser:

Code: Alles auswählen

import re

class Parser(object):
    def __init__(self, data):
        self.data = data
        self.tokens = re.finditer(r"\s+|[{},:]|\d+|.*?'",data)
        self.token = ''
        self.pos=0
        self._next_token()
        
    def _next_token(self):
        try:
            while True:
                self.pos+=len(self.token)
                self.token = self.tokens.next().group()
                if self.token.strip():
                    break
        except StopIteration:
            self.token=''

    def _expect(self, ch):
        if self.token!=ch:
            raise AssertionError('"%s" erwartet'%ch)
        self._next_token()

    def _get_string(self):
        if self.token[-1]!="'":
            raise AssertionError('String erwartet')
        result = self.token[:-1]
        self._next_token()
        return result
    
    def _get_typed_string_or_number(self):
        if self.token[-1]!="'":
            result=int(self.token)
            self._next_token()
        else:
            typ=self._get_string()
            if self.token[-1]!="'":
                result = typ
            else:
                value=self._get_string()
                result = (typ, value)
        return result

    def __iter__(self):
        return self
    
    def next(self):
        if not self.token:
            raise StopIteration()
        try:
            self._expect('{')
            result=dict(p for p in self.parse_entry())
            self._expect('}')
            self._expect(',')
            return result
        except:
            print self.data
            print ' '*self.pos+'^'
            raise
            
    def parse_entry(self):
        self._expect("u'")
        typ = self._get_string()
        self._expect(':')
        values=[]
        while True:
            values.append( self._get_typed_string_or_number() )
            if self.token=='}':
                yield typ, values
                break
            elif self.token==':':
                self._next_token()
                u = values.pop()
                yield typ, values
                if u[0]!="u":
                    raise AssertionError("u' erwartet")
                typ = u[1]
                values=[]
            else:
                self._expect(',')

txt="{u'p': n'schmitt', v'markus', u's': 1, u'w':hamburg'}, {u'p': n'schroeder', v'steffi', u's': 0, u'w':berlin'}, {u'p': n'meier', v'klaus', u's': 1, u'w':koeln'}, {u'p': n'bruns', v'dieter', u's': 0, u'w':berlin'},"
parser = Parser(txt)

for record in parser:
    if record['s']==[1]:
        print record
wayne
User
Beiträge: 5
Registriert: Dienstag 16. April 2013, 21:35

Danke für die schnellen antworten. Das spricht für dieses Forum :lol:

Ich werde jetzt die einzelnen Codes für mein script testen und dann berichten. 1000 dank erstmal an alle!!!!!


@Blackjack: Das Dateiformat sieht wirklich genauso aus.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

wayne hat geschrieben: @Blackjack: Das Dateiformat sieht wirklich genauso aus.
Viel wichtiger: Woher stammt das? Und: Kann man das ggf. ändern? (Wenn ja, greife *immer* auf Standardformate a la JSON, XML, YAML, INI, usw. zurück!)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
wayne
User
Beiträge: 5
Registriert: Dienstag 16. April 2013, 21:35

@Blackjack und @Hyperion

Ich erhalte diese Dateiformat wenn ich aus meiner Datenbank Profile auslese.

!!! Ich muss nun gestehen das ich einen fehler in meiner syntax hatte,und so eine falsche Ausgabe zustande kam. (sorryy and dieser stelle an Blackjack, war ne berchtigte Frage).

Ich kann leider nicht auf Standartformate zurückgreifen. Um dieses komische Dateiformat komme ich leider nicht drum rum. Die Aufgabe bestehet darin dies zu vollziehen.

Ich würde es denke ich hinkriegen den raw-String in ein lesbares XML-Format zuschreiben. Was bedueten würde, ich wandel das Dateifromat in ein XML-Format um und dann lese ich die gewünscht Information aus der XML. Es wäre jedoch eleganter und recourcen-sparend die Infos direkt aus dem raw-Format zu lesen und auszugeben. Was wäre denn die gängigere Methode???

Hier jetzt noch mal die korrekte Ausgabe:

a: [{u'n': u'schmitt', u'v': u'markus', u'i': u'0009678' , u's': 1, u'w': u'hamburg'}, {u'n': u'schroeder', u'v': u'steffi', u'i': u'0009679' , u's': 0, u'w': u'berlin'}, {u'n': u'meier', u'v': u'klaus', u'i': u'0009679' , u's': 1, u'w': u'koeln'}, {u'n': u'bruns', u'v': u'dieter', u'i': u'0009680' , u's': 0, u'w': u'berlin'}]

!!!!Hier nochmal zur bessseren Übersicht!!!

a: [
{u'n': u'schmitt', u'v': u'markus', u'i': u'0009678' , u's': 1, u'w': u'hamburg'},
{u'n': u'schroeder', u'v': u'steffi', u'i': u'0009679' , u's': 0, u'w': u'berlin'},
{u'n': u'meier', u'v': u'klaus', u'i': u'0009679' , u's': 1, u'w': u'koeln'},
{u'n': u'bruns', u'v': u'dieter', u'i': u'0009680' , u's': 1, u'w': u'berlin'}
]

Danke und Sorry an alle die Ihre codes gepostet haben. Ich hoffe ich hab nich verk@+*t :oops:

Es sind auf jedenfall einige Lösungsansätze zustande gekommen.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

wayne hat geschrieben:!!! Ich muss nun gestehen das ich einen fehler in meiner syntax hatte,und so eine falsche Ausgabe zustande kam.
Mit einem kleinen simplen regulären Ausdruck bekommst du alles was du brauchst.

Code: Alles auswählen

data = """a: [{u'n': u'schmitt', u'v': u'markus', u'i': u'0009678' , u's': 1, u'w': u'hamburg'}, {u'n': u'schroeder', u'v': u'steffi', u'i': u'0009679' , u's': 0, u'w': u'berlin'}, {u'n': u'meier', u'v': u'klaus', u'i': u'0009679' , u's': 1, u'w': u'koeln'}, {u'n': u'bruns', u'v': u'dieter', u'i': u'0009680' , u's': 0, u'w': u'berlin'}]"""
result = re.findall(r"u'n': u'(.*?)'.*?u'v': u'(.*?)'.*?u'i': u'(.*?)'.*?u's': (\d).*?u'w': u'(.*?)'", data)
for element in result:
    print element
Ergebnis:

Code: Alles auswählen

('schmitt', 'markus', '0009678', '1', 'hamburg')
('schroeder', 'steffi', '0009679', '0', 'berlin')
('meier', 'klaus', '0009679', '1', 'koeln')
('bruns', 'dieter', '0009680', '0', 'berlin')
BlackJack

@wayne: Dieses ”komische” Format sieht nach einer Zeichenkettendarstellung von einer Liste mit Dictionaries mit Unicode-Objekten und Zahlen aus. Da hat es sich jemand (vermeintlich) ganz leicht gemacht statt ein „echtes” Format zu verwenden.

Wobei ich nur zur Sicherheit noch mal nachfrage: Ist das wirklich eine Zeichenkette, die Du da bekommst, oder kann es sein, dass das schon eine Python-Datenstruktur ist und Du ein Problem zu lösen versuchst, was es gar nicht gibt? Was ist denn das für eine Datenbank?

Das lässt sich, weil's Python ist, sehr einfach mit `ast.literal_eval()` parsen:

Code: Alles auswählen

In [4]: ast.literal_eval(data)
Out[4]: 
[{u'i': u'0009678',
  u'n': u'schmitt',
  u's': 1,
  u'v': u'markus',
  u'w': u'hamburg'},
 {u'i': u'0009679',
  u'n': u'schroeder',
  u's': 0,
  u'v': u'steffi',
  u'w': u'berlin'},
 {u'i': u'0009679', u'n': u'meier', u's': 1, u'v': u'klaus', u'w': u'koeln'},
 {u'i': u'0009680', u'n': u'bruns', u's': 0, u'v': u'dieter', u'w': u'berlin'}]
wayne
User
Beiträge: 5
Registriert: Dienstag 16. April 2013, 21:35

@Blackjack

Ja es ist ein Python Datenstruktur. Das Problem besteht damit nach wie vor.

Wenn der Wert u's': 1 gegeben ist möchte ich die Werte u'v': u'markus' + u'n': u'schmitt' ausgegeben haben

am besten in klartext: markus schmitt.

danke bis hier hin

Ich habe bis jetz noch nicht soviel mit BAstrakten Syntax Trees gearbeitet. Aber vielen Dank bis hier her!

Das wir ne lange NAcht :lol:
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Ehm, wie wärs mit:

Code: Alles auswählen

for el in data:
    if el[u's']:
        print el
Ist jetzt nur die wilde Vermutung, das Du uns hier die ganze Zeit die repr-Version präsentierst.
BlackJack

@jerch: Das ist ja auch immer noch so eine Vermutung von mir, dass es sich zum Beispiel um eine NoSQL-Datenbank handelt die „nativ” JSON liefert was von der Python-Anbindung in eine entsprechende Python-Struktur umsetzt und das wir hier über Probleme reden die gar nicht wirklich existieren.
wayne
User
Beiträge: 5
Registriert: Dienstag 16. April 2013, 21:35

Es handelt sich um einen Ausscnitt von meiner Ausgabe mit nich realen Daten. ich kann wollte Ungern echte Userdaten posten.
BlackJack

@wayne: Darum geht es doch gar nicht. Es geht nicht um den Inhalt sondern um die Frage ob Du den Unterschied zwischen einer Datenstruktur und einer Zeichenkettendarstellung einer Datenstruktur verstehst. Ob das Problem überhaupt tatsächlich besteht oder ob das Problem nicht erst durch Deine Fehlinterpretation entsteht.

Bekommst Du von der Datenbank *tatsächlich* eine *Zeichenkette*? Was ist der Datentyp von dem Wert, den Du von der Datenbank bekommst? Den kann man mit der Funktion `type()` ermitteln.

Du vermittelst den Eindruck also solltest Du mal ein Grundlagentutorial durcharbeiten. Denn die Darstellung hätte man eigentlich ziemlich leicht als Python-Datenstruktur erkennen können und die Frage wie man da jetzt den Namen heraus bekommt, sollte man eigentlich selber beantworten können.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@wayne: Verrate uns doch (zusätzlich zu den Fragen von BlackJack), was für eine Datenbank Du ansprichst und ggf. auch noch mit welcher Lib.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten