Avatar billede sw_red_6 Nybegynder
13. august 2009 - 09:10 Der er 20 kommentarer og
2 løsninger

gem evt. kopier i 21346 items (fra XML) i ny fil...

Jeg har en xml-fil med 21436 items.
De items skal ind i en database, hvilket er nemt nok.
Problemet er at der findes duplikater af nogle af de items og duplikaterne skal skrives til en fil.

Jeg har forsøgt at gøre det ved at gemme ID og Key for hver item i et array og kigge det igennem for at se om den aktuelle Key er brugt i forvejen og gemme alle oplysninger om det aktuelle item i et andet array. Det er der bare ikke hukommelse nok til..

Jeg har også forsøgt at gemme ID og Key i alm. variabler, men så vil det kun virke hvis duplikaterne er lige efter hinanden, hvilket ikke er tilfældet.

Jeg kunne også forsøge at skrive det direkte til en fil, hver gang jeg har et duplikat, men det er jeg ikke meget for..

Nogen der kan komme med et brugbart forslag?
Avatar billede repox Seniormester
13. august 2009 - 09:26 #1
Det burde ikke være noget problem at have 21346 ID'er i et array.
Du må gøre noget 'forkert' når du kontrollerer om ID'et er i array'et?

Alternativt så lad databasen ignorere dubletter - det er absolut det nemmeste og det hurtigste.
Avatar billede olebole Juniormester
13. august 2009 - 09:36 #2
<ole>

Det er absolut ikke godt at bruge et array. Det er enormt ressourcekrævende - brug en hash tabel i stedet. Du kan:

$a = array(
    "Værdi A",
    "Værdi B",
    "Værdi C"
);
$oHash = array();

for ($i=0,$j=count($a); $i<$j; $i++) {
    if (oHash[$a[$i]]) {
        // Denne værdi er allerede indsat i DB
        // Indsæt i stedet i ny fil
    } else {
        // Indsæt i DB
        oHash[$a[$i]] = 1;
    }
}

Det er mange, mange gange hurtigere (og mindre hukommelseskrævende) end at bruge in_array  ;o)

/mvh
</bole>
Avatar billede olebole Juniormester
13. august 2009 - 09:38 #3
Nu viste jeg, at værdierne kom fra array'et $a - men i dit tilfælde kommer de jo fra en XML-fil. Det vigtige er at indsætte i - og teste mod - en hash tabel ($oHash)
Avatar billede sw_red_6 Nybegynder
13. august 2009 - 09:40 #4
Det skulle man tro..

Jeg har følgende kode som virker.

  $xmltemplate = simplexml_load_file($tmp);
  foreach($xmltemplate->Employees->Employee as $val) {
    $sql = "INSERT INTO temp_doctors SET
            KEY = '".$val->Key."',
            Username = '".$val->UserName."',
            eCode = '',
            RegionID = 3,
            Enabled = 'True',
            UserPermissions = (SELECT UserPermissions FROM sys_userroles WHERE UserRoleID = 15),
            HomePage = (SELECT HomePage FROM sys_userroles WHERE UserRoleID = 15),
            UserType = 15,";
    $sq2 = "FirstName = '".mysql_escape_string(utf8_decode($val->FirstName))."',
            LastName = '".mysql_escape_string(utf8_decode($val->LastName))."',
            Email = '".$val->Mail."'";
    $sq3 = "ON DUPLICATE KEY UPDATE ";
    mysql_query($sql.$sq2.$sq3.$sq2) or die("<pre>".$sql."</pre>".mysql_error());
    $pass = '';
    $length = 2;
    for($p=0;$p<$length;$p++) {
      $pass .= chr(97 + mt_rand(0,25));
    }
    $sql = "UPDATE temp_doctors SET eCode = CONCAT('sj',LAST_INSERT_ID(),'". $Pass ."') WHERE DoctorID = LAST_INSERT_ID()";
    mysql_query($sql) or die("<pre>".$sql."</pre>".mysql_error());
  }

I den kode har jeg forsøgt at indsætte det her lige før den sidst }
  $done[$x]['KEY']=$val->Key;
  $done[$x]['ID']=$val->ID;
  $x++;

Gør jeg det for jeg følgende fejl:
Fatal error: Allowed memory size of 16777216 bytes exhausted (tried to allocate 24 bytes) in /var/www/rsj_parse/RSJ_XmlParser.php on line 20
Avatar billede repox Seniormester
13. august 2009 - 09:46 #5
#2
Hvad er forskellen på dit array og OP's array? Bare lige for at få det udpenslet :)

#4
Hvorfor ikke gøre som jeg foreslog? Lad MySQL ignorere dubletterne, så har du ikke problemet?
Avatar billede sw_red_6 Nybegynder
13. august 2009 - 09:53 #6
#5
Fordi vi ikke ved hvilken en af kopierne er den rigtige..
Skulle nok have præciseret at det er Key som kan være genganger og ikke hele item..
Desuden vil det være sådan at XML-filen vil komme 1x dagligt og skal parses og databasen skal opdateres.
For at kunne undgå at de samme Keys bliver ved med at have duplikater vil vi lave en fil med duplikaterne som vi kan sende tilbage til dem vi modtager XML'en fra
Avatar billede olebole Juniormester
13. august 2009 - 09:56 #7
repox >> Jeg forstår ikke dit spørgsmål. Hvad mener du med OP's array?

Han skal have dubletterne ned i en fil, så det hjælper vel ikke bare at ignorere dem
Avatar billede olebole Juniormester
13. august 2009 - 09:57 #8
Ehhhh ... et array med flere ens keys ...?
Avatar billede sw_red_6 Nybegynder
13. august 2009 - 10:01 #9
hehe.. OP er mig ;o) - OP = Original Poster

#8 - Jeg er lige så lost som dig her.. hvad mener du?
Avatar billede repox Seniormester
13. august 2009 - 10:03 #10
#6
Så kan du jo bare kontrollere om dubletten bliver indsat i databasen eller ej, hvis ikke - smid i en fil.

#7
Sorry, skimtede dit indlæg for hurtigt igennem, jeg er med nu...
Avatar billede olebole Juniormester
13. august 2009 - 10:08 #11
repox >> Der er gigantisk forskel på at teste ned i et array, du bladrer igennem element for element og tester på det (det er det, in_array gør) - og at teste på, om en key eksisterer i et array (hash tabel). Ikke kun i PHP  ;o)
Avatar billede repox Seniormester
13. august 2009 - 10:12 #12
#11
Jeg er enig med dig.
in_array() bruger jeg også kun på relativt små arrays.
Jeg vil også gøre som du gør. :)
Avatar billede sw_red_6 Nybegynder
13. august 2009 - 12:15 #13
OK, hvordan får jeg så den hash tabel til at virke?

Jeg har forsøgt med
  $done[$val['Key']]=1;
men det virker ikke eftersom der ikke kommer til at stå noget i nøglen..'

  $done[$val->Key]=1;
Det kan ikke lade sig gøre fordi det ikke er muligt at bruge et objekt som nøgle i et array..

Hvordan skal det så gøres?
Avatar billede repox Seniormester
13. august 2009 - 12:19 #14
prøv med
...
$newKey = (int)$val->Key;
$done[$newKey] = 1;
...
Avatar billede olebole Juniormester
13. august 2009 - 12:48 #15
Jeg forstår ikke:

  $done[$val->Key]=1;
Det kan ikke lade sig gøre fordi det ikke er muligt at bruge et objekt som nøgle i et array..


Prøv:

<?php
$a = array();
$o = new stdClass();
$o->bla = "noget";
$a[$o->bla] = "noget andet";
print $a["noget"];
?>
Avatar billede olebole Juniormester
13. august 2009 - 12:49 #16
$val->Key er jo ikke et objekt, men en streng eller et tal  =)
Avatar billede repox Seniormester
13. august 2009 - 12:52 #17
#16

Jeg har også oplevet det problem som OP har med SimpleXML.
Du kan f.eks. godt skrive:
echo $val->key;

Men når du vil bruge den, eksempelvis som et index til et array, får jeg også den samme ballade. Jeg plejer at løse det ved at type caste det...
Avatar billede sw_red_6 Nybegynder
13. august 2009 - 12:57 #18
Korrekt, men jeg får den er besked hvis jeg forsøger..
Warning: Illegal offset type

Hvilket ifølge http://docs.php.net/types.array betyder at jeg forsøger at bruge et object eller array som nøgle
Avatar billede sw_red_6 Nybegynder
13. august 2009 - 13:53 #19
Det virkede, nu skal jeg så bare have fordelt pointene, så jeg skal bruge nogle svar..
Avatar billede repox Seniormester
13. august 2009 - 13:55 #20
Det fik du fra mig her
Avatar billede olebole Juniormester
13. august 2009 - 15:08 #21
- og her  =)
Avatar billede olebole Juniormester
13. august 2009 - 22:25 #22
Tak for points  =)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester