Keys van array_search functie worden verwisseld

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Ivar de Jong

Ivar de Jong

27/01/2014 00:29:59
Quote Anchor link
Ik heb een script geschreven dat door middel van array_search waarden in de juiste kolom van een CSV bestand plaatst door te vergelijken met de header. Het loopt door een lijst met producten en kent keys toe aan de waarden. Vervolgens worden de keys vergeleken met de keys in de header en zouden de waarden in de juiste kolom terecht moeten komen.

Momenteel loop ik tegen 2 problemen aan:

1. De waardes worden verwisseld.
2. Als een rij geen waarde bevat voor de desbetreffende kolom wordt deze niet overgeslagen in de CSV.

Mijn eerste vraag: Waarom worden de keys van een array_search functie verwisseld.

Dit is mijn script:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$spec
= $product->thirdPartyInfo->specifications->specification;
if (is_array($spec)){
    foreach($spec as $specification){
        $texualDescription = $specification->textualDescription->_;
        $value = $specification->value->_;

        $place = array_search($texualDescription, $header);

        if($place !== false){
            $row[$place] = $value;

            echo "place in array: ".$place."Value: ".$row[$place]."<br/>";
        }

    }
}

?>

Hieronder zie je de resultaten van het draaien ervan:

place in array: 7 Value: Electronic HP Care Pack Support Plus 24 with Comprehensive Defective Material Retention Post Warranty - uitgebreide serviceovereenkomst - 1 jaar - ter plaatse
place in array: 8 Value: Uitgebreide serviceovereenkomst
place in array: 9 Value: Onderdelen en werkuren
place in array: 10 Value: Ter plaatse
place in array: 11 Value: 1 jaar
place in array: 15 Value: 4 uur
place in array: 13 Value: 24 uur per dag / 7 dagen per week

Zoals je kunt zien gaat het toewijzen van de keys verkeerd, er staat 7,8,9,10,11,15,13 terwijl er zou moeten staan: 7,8,9,10,11,13,15

Mijn tweede vraag: Waarom worden lege kolommen niet overgeslagen tijdens het schrijven van de CSV file met fputcsv


Zoals je hierboven in de lijst kunt zien zouden kolom 12 en 14 moeten worden overgeslagen (oftewel leeg moeten blijven) omdat daarvoor in die rij geen waarde beschikbaar is. Maar wat er gebeurt is dat de waarden voor kolommen 13 en 15 worden geplaatst in kolom 12 en 13.

Ik heb geprobeerd een extra komma to te voegen als waarde voor de kolom als er geen match gevonden wordt maar dat werkte ook niet. Zie hieronder mijn code voor dat gedeelte:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$spec
= $product->thirdPartyInfo->specifications->specification;
if (is_array($spec)){
    foreach($spec as $specification){
        $texualDescription = $specification->textualDescription->_;
        $value = $specification->value->_;

        $place = array_search($texualDescription, $header);

        if($place !== false){
            $row[$place] = $value;

            echo "place in array: ".$place."Value: ".$row[$place]."<br/>";
        }

        else($row[$place] = ",");
    }
}

?>

Heeft iemand misschien een idee waarom dit niet zo werkt als ik in theorie had bedacht en het liefst ook een oplossing zodat het wel werkt.
Het probleem aanwijzen zou me al een hoop helpen want ik staar me nu al een week blind op dit stukje code en ik kom geen steek verder.

Alvast dank!
Gewijzigd op 27/01/2014 00:40:07 door Ivar de Jong
 
PHP hulp

PHP hulp

07/05/2024 13:42:42
 
Erwin H

Erwin H

27/01/2014 08:57:24
Quote Anchor link
Om met je tweede vraag te beginnen, wat noem jij een 'lege waarde' in die array. Heb je het eigenlijk niet over een niet bestaande waarde? Heb je een array met keys 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15. Of een array met keys 1,2,3,4,5,6,7,8,9,10,11,13,15. In het tweede geval bestaan de keys 12 en 14 niet en zullen die dus ook niet gebruikt worden. Php vult niet automatisch ontbrekende keys aan en zal dus niet bestaande keys ook niet printen.

Hiermee kom je ook op een mogelijk antwoord voor je eerste vraag. De volgorde van de keys is niet per definitie gelijk aan de nummering. Als je keys in deze volgorde zijn toegevoegd: 1,2,3,4,5,6,7,8,9,10,11,15,13 dan komen de waardes ook in deze volgorde eruit.

Arrays zijn rare dingen in php waarbij je niet zomaar kan vertrouwen op de logica die je zou verwachten. In feite is een array een linked list in php waarmee elk toegevoegd element gewoon aan het einde wordt geplaatst, zonder dat er naar de keys wordt gekeken. Een numerieke key is dus in feite gelijk aan een string key.

wat je denk ik kan doen om beide problemen in 1 klap op te lossen, is vooraf een array te definieren met het correcte aantal elementen, met lege waardes. Dan zijn direct al je keys daar en in de goede volgorde:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
//definieert een array met 15 elementen, beginnend bij key 1
$row = array_fill( 1, 15, '' );
?>
Gewijzigd op 27/01/2014 09:02:06 door Erwin H
 
Ivar de Jong

Ivar de Jong

27/01/2014 11:09:55
Quote Anchor link
Dank voor je reactie!

Het is me nu duidelijk dat de keys worden toegevoegd op basis van de volgorde van de input. Ik heb het niet over een "lege waarde" in de array maar over een lege cel in een bepaalde kolom in de CSV.
Als een waarde met de key niet bestaat in het array van values maar wel in de header moet hij die gewoon overslaan...Er is immers geen matchende key in de ingevoegde rij.

In principe worden die keys die worden toegekend aan de gevonden waarden vergeleken met de keys die zijn toegekend aan de header kolommen. De header wordt eerder aangemaakt op basis van dezelfde lijst met waarden.
Dus de value die hoort bij key nummer 11 moet worden ingevoerd in kolom 11. Je zou zeggen dat het op die manier niet kan missen.

Je oplossing met het van tevoren definiëren van het aantal elementen zou een goede oplossing zijn ware het niet dat het niet altijd 15 kolommen zijn.
De csv wordt opgebouwd uit een xml file waarbij met een foreach bepaalde waarden worden gehaald.
Dit verschilt per bestand dus ik kan niet van tevoren zeggen hoe groot het array zal gaan worden.

De oplossing daarvoor zou zijn om een count te doen op het aantal waarden maar dat betekent weer een extra loop. Gezien het feit dat dit script binnen een korte tijd +/- 6500 csv bestanden moet schrijven wil ik het aantal loops zo veel mogelijk beperken.

Ik begrijp nogsteeds niet goed waarom het mappen van de kolommen op basis van de keys verkeerd gaat. Ze worden met elkaar vergeleken en 15 = 15 en niet 12...
Gewijzigd op 27/01/2014 11:20:11 door Ivar de Jong
 
Erwin H

Erwin H

27/01/2014 11:29:18
Quote Anchor link
Ivar de Jong op 27/01/2014 11:09:55:
Je oplossing met het van tevoren definiëren van het aantal elementen zou een goede oplossing zijn ware het niet dat het niet altijd 15 kolommen zijn.
De csv wordt opgebouwd uit een xml file waarbij met een foreach bepaalde waarden worden gehaald.
Dit verschilt per bestand dus ik kan niet van tevoren zeggen hoe groot het array zal gaan worden.

Dat maakt helemaal niet uit. Je weet toch hoeveel headers er zijn? Dan weet je hoeveel kolommen je in elke rij moet hebben. Dat is dus niet eens een extra loop, het is simpelweg even het aantal headers tellen (en als die in een array staan is dat een simpele count).

Ivar de Jong op 27/01/2014 11:09:55:
Het is me nu duidelijk dat de keys worden toegevoegd op basis van de volgorde van de input. Ik heb het niet over een "lege waarde" in de array maar over een lege cel in een bepaalde kolom in de CSV.
Als een waarde met de key niet bestaat in het array van values maar wel in de header moet hij die gewoon overslaan...Er is immers geen matchende key in de ingevoegde rij.

Daar ga je denk ik mis. "Gewoon overslaan" bestaat dus niet. Je hebt of een lege waarde, of geen waarde. Heb je geen waarde dan krijg je het probleem dat je nu hebt. Heb je een lege waarde op de juiste plek in de array dan werkt het wel.

Ivar de Jong op 27/01/2014 11:09:55:
In principe worden die keys die worden toegekend aan de gevonden waarden vergeleken met de keys die zijn toegekend aan de header kolommen. De header wordt eerder aangemaakt op basis van dezelfde lijst met waarden.
Dus de value die hoort bij key nummer 11 moet worden ingevoerd in kolom 11. Je zou zeggen dat het op die manier niet kan missen.

Jawel dus. Want als je eerst nummer 12 vindt en dan nummer 11 dan staan ze omgekeerd.


Toevoeging op 27/01/2014 11:34:45:

Maar volgens mij kan je je header search ook nog wat vereenvoudigen, bouw de header array anders op:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$headers
= array(
    kolom_header_naam => plaats_in_array
);

//dit zou dan worden
$headers = array(
    'product_naam' => 3,
    'prijs' => 4,
    'omschrijving' => 11,
    //etc
);
?>

Je maakt de key in die headers kolom dus de header naam en de value de plek. Dan hoef je niet meer met array search aan de gang, maar kan je direct de juiste plek vinden:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
$row
[$headers[$specification->textualDescription->_]] = $specification->value->_;
?>

De eerdere oplossing met de lege array voor elke rij heb je nog steeds nodig, maar volgens mij is dit veel sneller omdat je nooit meer een search hoeft te doen.
Gewijzigd op 27/01/2014 11:35:52 door Erwin H
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.