Gå til innhold

Python - Beste måten å lagre data på?


Anbefalte innlegg

Hei!

Ønsker å lagre ett slikt oppsett for å lett kunne hente det fram igjen:

d = {"first":("foo", "bar"), "second":("foo", "bar"), "third":("foo", "bar")}

Enkelt og greit, en dict med navn, som inneholder forskjellige elementer med to forskjellige verdier. Disse verdiene må stå i rett rekkefølge.

Tror ikke antall elementer kommer til å passere 500, så hastighet/effektivitet har ikke noe si. Vil lagre dem så oversiktlig/human-readable som mulig, slik at jeg lett kan manipulere dataen både manuelt og med kode.

Hvilken lagrings måte foreslår dere(lokalt, ingen mysql database)?

Json, csv, osv, eller lagre hele greien og loade filen med eval(),noe jeg vil unngå?

 

Når det kommer til lagring generelt, hvilke metoder er best for hvilke formål?

 

Jeg skal kunne søke etter elementer i denne dict'en etter navn, og siden disse navnene kan bli ganske lange, vil jeg ha med en prosentvis "did you mean?" funksjon. Hvordan får jeg det til?

 

Takk på forhånd!

Endret av Axxxy
Lenke til kommentar
Videoannonse
Annonse

Jeg antar at Python 3 benyttes, så jeg har ikke tatt i betraktning hvordan koden skal se ut med Python 2.

 

Jeg kan ikke si at jeg vet om den beste måten å lagre data på, fordi det bl.a. kommer an hva du skal lagre, hvor mye, portabilitet osv. Hvis du ikke bryr deg om hvordan selve dataen ser ut, kan du se på noe som pickle, som er ment til å enkelt serialisere Python-objekter.

 

Hvis du skal ha noe med høy lesbarlet er JSON ganske greit til enkel data, og resultatet er så klart portabelt. Eksempel på «Pretty printing»:

>>> import json
>>> d = {"first":("foo", "bar"), "second":("foo", "bar"), "third":("foo", "bar")}
>>> print(json.dumps(d, indent=4))
{
    "second": [
        "foo",
        "bar"
    ],
    "third": [
        "foo",
        "bar"
    ],
    "first": [
        "foo",
        "bar"
    ]
}

Men her har vi et lite problem... Problemet med å bruke en vanlig dictionary er at den ikke lagrer posisjon, bare key/value pairs. Det er altså en unordered dictionary.

 

For å løse problemet kan du bruke en ordered dictionary.

>>> from collections import OrderedDict
>>> import json
>>> d = OrderedDict([("first", ("foo", "bar")), ("second", ("foo", "bar")), ("third", ("foo", "bar"))])
>>> print(json.dumps(d, indent=4))
{
    "first": [
        "foo",
        "bar"
    ],
    "second": [
        "foo",
        "bar"
    ],
    "third": [
        "foo",
        "bar"
    ]
}

Selv om resultatet nå ser bra ut betyr det fortsatt ikke at det er den beste måten å lagre data på generelt. Det funker dog helt greit til eksemplet du viser, fordi det er helt enkle typer som JSON-biblioteket vet hvordan den skal serialisere. Skal du f.eks. også lagre binærdata er ikke JSON en god løsning rett ut av boksen, siden den ikke kan serialisere binærdata for deg. Jeg tror du fortsatt kan lage din egen JSONEncoder/JSONDecoder hvis du også vil støtte binærdata.

 

La oss bare ta et eksempel på hva som ikke virker:

>>> from collections import OrderedDict
>>> import json
>>> d = OrderedDict([("first", (b"foo"))])
>>> print(json.dumps(d, indent=4))
Traceback (most recent call last):
  [snip]
TypeError: b'foo' is not JSON serializable

Hvis du ikke trenger å serialisere binærdata, har du så klart mindre å bekymre deg for.

Endret av ahw_
  • Liker 2
Lenke til kommentar

Jeg laget en liknende funksjonalitet en gang i Java, der tabeller ble lagret som excel-ark. Finnes sikkert mange gode bibliotek som kan skrive/lese excel-ark også for Python.

 

Det er i hvert fall veldig enkelt å endre på "manuelt" også :)

Nå har jeg dessverre ikke Office pakken, men det er jo ett godt alternativ!

 

 

Jeg kan ikke si at jeg vet om den beste måten å lagre data på, fordi det bl.a. kommer an hva du skal lagre, hvor mye, portabilitet osv. Hvis du ikke skal lagre så altfor mye og du ikke bryr deg om hvordan selve dataen ser ut, kan du se på noe som pickle, som er ment til å enkelt serialisere Python-objekter.

 

Hvis du skal ha noe med høy lesbarlet er JSON ganske greit til enkel data, og resultatet er så klart portabelt. Eksempel på «Pretty printing»:

>>> import json
>>> d = {"first":("foo", "bar"), "second":("foo", "bar"), "third":("foo", "bar")}
>>> print(json.dumps(d, indent=4))
{
    "second": [
        "foo",
        "bar"
    ],
    "third": [
        "foo",
        "bar"
    ],
    "first": [
        "foo",
        "bar"
    ]
}

Men her har vi et lite problem... Problemet med å bruke en vanlig dictionary er at den ikke lagrer posisjon, bare key/value pairs. Det er altså en unordered dictionary.

 

For å løse problemet kan du bruke en ordered dictionary.

 

JSON it is!

Ser nå at jeg beskrev det litt vanskelig:

Dict'en vil inneholde mange elementer. Disse elementene vil bli referert til med navn, som i dette tilfelle er first, second, third, etc. Disse navnene trenger ikke å være sorterte.

Verdiene til disse navnene vil være en tuple med to verdier, som i dette tilfellet er foo, bar. Disse verdiene derimot, må være sortert for å holde orden i systemet.

 

Tusen takk for utdypende svar, noe som kan komme godt med senere.

 

Noen som vet svaret på det andre spørsmålet jeg spurte? Dict'en vil inneholde elementer der enkelte kan ha lange navn, derfor skal jeg legge inn en "did you mean?", funksjonalitet. Hvordan? :)

Lenke til kommentar

Siden jeg trodde at first/second/third måtte beholde riktig posisjon, tok jeg dessverre med et eksempel på dét også i mitt redigerte innlegg (etter at du begynte å skrive svaret).

 

Må innrømme at jeg først ikke helt skjønte hva du mente med «did you mean?». Man skal altså kunne lete opp en key selv om navnet ikke er skrevet helt ut eller har noen skrivefeil?

 

I så fall er det en slags «key resolver» man vil lage, og jeg vet egentlig ikke om Python har noe slikt til dict. Det går vel egentlig litt i mot det en dictionary er ment for, og vil naturligvis være tregt ift. vanlig dict. Da blir kanskje alternativet å gå gjennom hver eneste key (rekursivt?) og teste hver eneste key?

 

Fant faktisk noe her: Fuzzy matching dictionary.

 

Ser ut som den typen løsning du ber om?

Endret av ahw_
Lenke til kommentar
Må innrømme at jeg først ikke helt skjønte hva du mente med «did you mean?». Man skal altså kunne lete opp en key selv om navnet ikke er skrevet helt ut eller har noen skrivefeil?

Tror det er noe i denne stilen han mener.

user_input = 'firsttt'
record = {"first":("foo", "bar"), "second":("foo", "bar"), "third":("foo", "bar")}
if user_input in record:
    print record[user_input]
else:
    print '<{}> not found in record'.format(user_input)

Funksjon med dicionary get method.

def foo(user_input):
    return {
      "first": "foo", "bar"),
      "second": "foo", "bar"),
      "third": "foo", "bar")
     }.get(user_input, '<{}> not found in record'.format(user_input))

if __name__ == '__main__':
    user_input = 'ffirst'
    print foo(user_input)
Endret av snippsat
Lenke til kommentar
user_input = 'firsttt'
record = {"first":("foo", "bar"), "second":("foo", "bar"), "third":("foo", "bar")}
if user_input in record:
    print record[user_input]
else:
    print '<{}> not found in record'.format(user_input)

Njo. Poenget er at 'firsttt' skal kunne refereres til 'first' selv om det står skrevet feil, men kun om feilen ikke er for stor. La oss si at vi setter en likhetstoleranse på 10-20%.

>>> chkSimilar('firdt', 'first', 20) //sjekke om input1 er =~ input2, med x prosent(%)
True
>>> chkSimilar('firdty', 'first', 20)
False

//Da kan jeg i steden for ditt eksempel:
d = dict()
if input in d:
    print d[input]

//Men heller:
d = dict()
percentage = 20 //denne verdien blir forandret etter behov
for item in d:
    if chkSimilar(input, item, percentage):
        print d[item]

Endret av Axxxy
Lenke til kommentar

Da blir kanskje alternativet å gå gjennom hver eneste key (rekursivt?) og teste hver eneste key?

 

Ja, og det er ingen problem da listen mest sannsynlig ikke vil inneholde mer enn 500 elementer.

 

 

Fant faktisk noe her: Fuzzy matching dictionary.

 

Ser ut som den typen løsning du ber om?

Ja, dette ser lovende ut!

 

Beklager dårlig forklaring :hm: Men det var dette jeg mente:

input = ''firdt" -> did you mean = "first"?

 

EDIT:

Søkte på "python fuzzy", og fant denne som også er relevant. Her har man kanskje litt mer kontroll også: http://streamhacker.com/2011/10/31/fuzzy-string-matching-python/

 

EDIT 2:

Her har vi en flott modul:

https://pypi.python.org/pypi/python-Levenshtein/0.11.2

 

Fyrer inn en liten smake bit. Dette er 3 av 17 funksjoner jeg fant i modulen.

docstrings
// distance = compute absolute Levenshtein distance of two strings
// ratio =    compute similarity of two strings
// editops =  find sequence of edit operations transforming one string to another

//Distance
>>> import levenshtein
>>>
>>> levenshtein.distance('abcd', 'abcd')
0
>>> levenshtein.distance('abcd', 'abdc')
2
>>> levenshtein.distance('skriefeil her og der', 'skriveleif der og her')
5

//Ratio
>>> levenshtein.ratio('abcd', 'abcd')
1.0
>>> levenshtein.ratio('abcd', 'abdc')
0.75
>>> levenshtein.ratio('skriefeil her og der', 'skriveleif der og her')
0.7804878048780488

//Editops
>>> levenshtein.editops('skrivefeil', 'skriveleif')
[('replace', 6, 6), ('replace', 9, 9)]
>>> levenshtein.editops('haha', 'hahy')
[('replace', 3, 3)]
Endret av Axxxy
  • Liker 1
Lenke til kommentar

 

Hvordan har du tenkt å regne Levenshtein-avstanden mellom brukerinput og *alle* nøklene i datastrukturen din?

 

(for 500 nøkler går det an å gjøre det rett frem bare ved å iterere over nøklene, men har du tenkt på hvordan man skulle gått frem om man hadde 50'000 nøkler?)

 

Nå var poenget at jeg kommer ikke til å ha en datastruktur med mer enn 500 elementer. Derfor fungerer det fint å bare iterere over listen.

Den dagen det blir ett prosjekt med 50K nøkler, da kan vi begynne å tenke på hvordan vi skal løse det :)

For øyeblikket er dette godt nok i massevis.

 

 

Kom over en god artikkel om temaet, som tilfeldigvis hadde eksemplet i python. Absolutt verd å ta en titt på.

http://norvig.com/spell-correct.html

Ja, den så jeg her om dagen! Denne krever jo en liten database over ord for å ha noe å referere til.

Begge disse verktøyene vil jo være sterke hånd i hånd, og er greit å vite om til den dagen det trengs :)

Lenke til kommentar

 

Jeg laget en liknende funksjonalitet en gang i Java, der tabeller ble lagret som excel-ark. Finnes sikkert mange gode bibliotek som kan skrive/lese excel-ark også for Python.

 

Det er i hvert fall veldig enkelt å endre på "manuelt" også :)

 

Nå har jeg dessverre ikke Office pakken, men det er jo ett godt alternativ!

 

Jeg regner med det skal fungere fint med OpenOffice også. Da har du i hvert fall en nødløsning om du ikke finner på noe bedre ;)

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...