[megoldva] php -> py

Segítene valaki átfogalmazni Pythonban ezt a PHP-s alapszkriptet?
Egyszer már nekiszaladtam, de a beolvasott tömb többszöri felhasználása nem volt triviális (valami iterációs mutatót kellett volna nullázni hozzá).


<?php
fclose(STDOUT); $STDOUT = fopen('out.valami', 'w');

define('d',";");
define('n',"\n");
$f_=file('in.valami',FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

foreach($f_ as $i=>$f){
if ($i==0) continue;
$x=explode(d,$f);
// print_r($x);die;
// [0] => 000001
// [1] => 000023
// [2] => 00191
print implode(d,$x).n;
}

foreach($f_ as $i=>$f){
print $f.n;
}

?>

Szerk: és az empty függvény legfontosabb (warning-kiküszöbölő) funkcióját jól ellátja a https://www.tutorialspoint.com/python/dictionary_setdefault.htm

Hozzászólások

Phpben a reset($f_); vissza pörgeti az effedet az elejére. Pythonban nem programoztam sose, de gondolom hasonló. Amúgy ez valami táblákat olvasba be majd kiíratod a képernyőre? Első ránézésre hibásnak tűnik. Inkább írd le mit akarsz, mit kell csináljon a kód.

Nekem is úgy tűnik van pár vérző sebe, de attól még működhet.

Mondjuk, az nem világos miért kell visszaállítani, a foreach a tömb másolatán dolgozik, nem változik a tömb mutatója:
http://php.net/manual/en/control-structures.foreach.php

In PHP 5, when foreach first starts executing, the internal array pointer is automatically reset to the first element of the array. This means that you do not need to call reset() before a foreach loop.
As foreach relies on the internal array pointer in PHP 5, changing it within the loop may lead to unexpected behavior.
In PHP 7, foreach does not use the internal array pointer.

Ez egyébként valami pontosvesszős-csv feldolgozás akar lenni? Mert akkor pythonban csv.reader alkalmasabbnak tűnik a feladatra, mint ezt portolni.

(a php kódban az fgetcsv/ str_getcsv amúgy szintén alkalmas lett volna, nem kell vacakolni az idézőjel escape-eléssel, többsoros mezőkkel, kommentekkel stb., tudják.)

Gyakran előforduló feladat, hogy (idézőjelmentes) pontosvesszős-csv-t kell feldolgoznom. Ilyenkor ezzel a szkripttel indulok, gyorsan belerakom azt a pár valamit, ami kell (mondjuk kiegészíteni egy új mezővel, vagy szűrni valamire vagy cserélni valamit), majd hadd szóljon. Kb. 2 perc alatt sokkal egyszerűbben meg tudok így oldani apróbb átalakításokat, mintha adatbázisba olvasnám stb.

A szkript egyébként (Ubuntu linuxon) hibátlanul fut, és nem is kell újraállítani a $f_-et az újra-ciklizáláskor sem (erre ritkán van amúgy szükség, talán egyszer volt, de akkor épp ez akasztott meg a pythonra portolásban).

Időnként fellángol bennem a késztetés, hogy az avíttnak tudott PHP helyett a trendi pythonban kezdjek el ügyködni, és abban javuljon a napi kézügyességem.

(Windowson ez a rész nem szokott menni, csak más formában: fclose(STDOUT); $STDOUT = fopen('out.valami', 'w'); )

Végigmegyek a sorokon, a delimiter (ált. pontosvessző) mentén tömbbe robbantom, majd valamit csinálok a tömbbel (pl. a második mezőhöz hozzáfűzöm, hogy bruhaha), aztán kiírom az újra egybeolvasztott sort.

S aztán még egyszer végigmegyek a fájl sorain és kiírom őket.

Ez kiindulásnak jó lehet. Lehetne tömörebb, "pythonosabb" is, de így érthetőbb egy kezdőnek.



fout= open("out.valami","w")
finp= open("in.valami")

xx=[]

for index,line in enumerate(finp):

    if index==0:
        continue
    line=line.strip()
    x= line.split(";")
    xx.append(x)
    print(x[0])
    print(x[1])

    s= ";".join(x)
    print(s,file=fout)

for ss in xx:
    #print(ss,file=fout)
    print(ss)

fout.close()
finp.close()

--
eutlantis

A fájlt soronként olvassuk be; az "open" nem tárolja le a fájlt automatikusan egy változóba. A "line" változóba mindig a következő sor kerül be, azaz a teljes fájl csak egyszer kerül tárolásra, mégpedig az xx-ben.
1) Ha nem szükséges az egész fájl egyidejű megléte egy változóban, akkor az xx-ben való tárolás nyilván elhagyható.
2) Ha a fájlt lezárjuk és újra megnyitjuk, akkor az elejétől kezdve újra beolvashatjuk a sorokat (ez másképp is megtehető egyébként) és nem kell az xx, de így általában lassabb lesz a folyamat.

--
eutlantis

Nem.


for line in ff:  # a szöveges fájlt beolvassa soronként

for index,line in enumerate(ff): # plusz még a sorszámot is megadja

Tömbre is működik:
for elem in xx:

for index,elem in enumerate(xx):

Tömböt természetesen indexelhetsz is (fájlt nem):
for i in range(len(xx)):
   xx[i]=xx[i]*2

--
eutlantis


Időnként fellángol bennem a késztetés, hogy az avíttnak tudott PHP helyett a trendi pythonban kezdjek el ügyködni, és abban javuljon a napi kézügyességem.

Ez bennem is sokszor fellangol, de aztan hamar elhal ha valamit gyorsan meg kell csinalni :)

Star Citizen referral: STAR-CX9F-NJ2B

Megnézem, köszi! :-)

[off: ...Alapjövedelem! Yess, egy srófra jár az agyunk, ennek örülök! :-)

S ez is milyen klassz! Be is szereztem a könyved: http://www.interkonyv.hu/konyvek/koos_antal_python_a_gepben – tetszenek az igényes magyarításaid, s hogy explicite ki is térsz ezekre. ]

Ugyan már született megoldás, és nem vagyok Python guru*, de valamikor így oldottam meg a CSV file beolvasását:


def csv2list(csvFile, data):
     with open(csvFile) as rf:
         csvDatas = csv.reader(rf, delimiter=';')
         for row in csvDatas:
             data.append(row)
     return data

CSV exportra nem volt szükségem, de a csv.writer(…) sem lehet túl bonyolult.

*: Tehát akár még hiba is lehet a megvalósításban.

Készítettem egy mérést egy python és php program futásról:

time ./step1.py
real 0m0.785s
user 0m0.732s
sys 0m0.048s

time ./step1.php
real 0m0.390s
user 0m0.268s
sys 0m0.116s

A két program:

fout= open("out.valamiPY","w")
finp= open("in.valami")

for index,line in enumerate(finp):
  line=line.strip()
  x= line.split(";")
  x[3]+='uuu';
  s=";".join(x)
  print(s,file=fout)

fout.close()
finp.close()

---

fclose(STDOUT); $STDOUT = fopen('out.valamiPHP', 'w');
define('d',";");
define('n',"\n");
$f_=file('in.valami',FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach($f_ as $i=>$f){
  $x=explode(d,$f);
  $x[3].='uuu';
  print implode(d,$x).n;
}

A használt in.valami fájl 47MB-os, 61503 soros, 95 oszlopos .csv, az eredményként adódó fájlok nem különböztek.

Egy ~130000 soros/95 oszlopos csv-vel tesztelve awk és python (2.6.5) fej-fej mellett nálam, gyakorlatilag mérési hibahatáron belüli eltérés van a futási idők között.
A python nagyjából mint fent (f.write a print helyett), az awk:


awk -F\; 'BEGIN { OFS=";"} {$4=$4"uuu"; print }' < in.csv > outawk.csv

Még egy kérdésem lenne, ami a PHP-ről való átállást segítené.
Gyakran jött jól az empty() függvény a PHP-ben, ami akkor adott vissza igaz értéket, ha a függvény argumentuma nem volt definiálva, vagy 0 volt, vagy üres sztring. Szerencsére tömbelemekre is rá lehetett kérdezni (anélkül, hogy warning érkezett volna a nemlétező index miatt).

Ehhez hasonló egyszerűségű függvényt tudnátok-e javasolni Pythonban?
Látok egy ilyet: https://stackoverflow.com/questions/1592565/determine-if-variable-is-de…, de nem szeretnék try-except ügyekkel bajlódni, ha nem muszáj, ez meg olyan bonyi: 'a' in vars() or 'a' in globals() or 'a' in locals() 'a' in vars(__builtin__) or a==0 or a==''
Meg egy ilyet is látok, de ez sem gusztusos: https://stackoverflow.com/questions/9390126/pythonic-way-to-check-if-so…

http://php.net/manual/en/function.empty.php

Vizsgálódáshoz használom pontosan azért, hogy ne dobjon warningot. Nem jut eszembe konkrét példa de visszanézem mikor használtam.

Szerk.:
Tessék:
function filterArr($input) {
$input = array_filter($input);
reset($input);
if (empty($input)) {
return false;
}
else {...


if not input:
  return False

pythonban az üres tömb, dict, tuple az false logikai érték is egyben.

===============================================================================
// Hocus Pocus, grab the focus
winSetFocus(...)

http://c2.com/cgi/wiki?FunnyThingsSeenInSourceCodeAndDocumentation

Egy szemenszedett példa: szeretnénk kimutatni, hogy egy iskola diákjai közül kinek nincs regisztrálva a mobiltelefonszáma.
A diákokat diákigazolványszám alapján tartjuk nyilván.

Első körben végigmegyünk a (korábban már kitöltött) diákok -> regisztrált mobiltelefonszámok tömbjén (neve legyen $repo), és a $mobil tömbben beállítjuk, kinek mi a(z egyik) mobilszáma. Lehet olyan opció is, hogy valaki nem ad meg telefonszámot, csak annyit közöl, hogy van telefonja; ilyenkor üresen hagyjuk (de felvesszük) a tömb értékét.

Aztán egy másik ciklusban végigmegyünk az iskola összes diákján, és ahol empty a $mobil[$diákigazolványszám] (akár azért, mert nem volt megadva semmi, akár azért, mert üres volt megadva) ott kiírjuk az érintettet.

Ez nem való életből vett példa, csak egy gyors "efféle már volt" leírás.

Amúgy meg nincs lelkiismeretfurdalásom amiatt, hogy az átláthatóbb megoldás kedvéért kétszer is nekiszaladjak egy ciklussal egy-egy hasonló tömbnek (merthogy a két ciklus tartománya nem ugyanaz, ha megnézed). Azt a két tizedmásodperces többlet-futást esetleg megérheti.

Most átterelitek a témát egy bazmeg-de-béna irányba? Mert úgy kitörlöm az egész bejegyzést innen, mint a pistike.

A kérdés az "empty" pythonos megfogalmazásáról szólt, nem programozási módszerekről, pláne nem példaeset-ócsárlásról.

Van egy üres array. Hogy vizsgálod meg gyorsan? Isset() nem jó, mert true. Létezik, csak üres.
$foo = array();
Ha vizsgálat nélkül nekimész és műveletet akarsz vele végezni, akkor az üresség miatt dob egy hibát.
IF (!empty($foo))...
Ettől mit tudsz egyszerűbbet mutatni?

Ja igen bocs a dragi volt az nem te. Az ő kommentje szúrt szemet. "Normálisan programozol" rész kiváltképp... Ezután meg a "pistike"... Azóta is mutatja mi az a normális programozás. Pl. van egy X funkciód az Y program nyelvben amivel Z dolog könnyebben, rövidebb kóddal megoldható. Erre ő aszongya csakazértis ABC módszer a jó, és punktum. Aki Xet használ nyomi amatőr. Én meg azt, hogy jobban ismeri azt a nyelvet és hatékonyabban kódol. Na mindegy. Ennyi.

részben, lehet.

nem phpzok, pythonhoz is csak hobbi szinten van közöm.
de kifejezetten érdekel egy olyan probléma, ahol egy ilyen függvényre szükséged lehet:

Determine whether a variable is considered to be empty. A variable is considered empty if it does not exist or if its value equals FALSE.

én nem tudok neked ilyet mondani (a fenti sem ilyen), de azt hiszem, bővítené a látóköröm.
--
blogom

Én valószínűleg egyetlen struktúrában tárolnám az adatokat és nem külön-külön tömbökben. De bárhogy is lenne, a meg nem adott mobilszámokat a None-nal (Pythonról van szó) jelölném; és például az üres sztringgel, ami "", ha nincs megadva a szám, de tudjuk, hogy létezik; vagy 0-val.
Mind a három esetben False lesz az eredmény az alábbi kifejezésben:


if egy_mobilszám:
  print( egy_mobilszám)

--
eutlantis

két meglátás a pythonhoz:
- nem tudom, mennyire korlátozottak a csv-k (pl.: escape-elve vannak-e benne enterek? pontosvesszők?), amiket fel kell dolgoznod, de egy ilyet megnéznék: https://docs.python.org/3/library/csv.html
- s

try-except KeyError

helyett szerintem szebb az

if key in map-else

, de keveset pythonozok ahhoz, hogy ebben döntő szó legyen az enyém.
--
blogom