2011-12-02 5 views
19

J'ai des valeurs csv comme ceci:str_getcsv dans un tableau multidimensionnel en php

$csv_data = "test,this,thing 
      hi,there,this 
      is,cool,dude 
      have,fun"; 

Je veux prendre une chaîne CSV entier et le lire dans un tableau multidemensional pour que je sois:

array(
    array(
     'test' => 'hi', 
     'this' => 'there', 
     'thing' => 'this' 
    ), 
    array(
     'test' => 'is', 
     'this' => 'cool', 
     'thing' => 'dude' 
    ), 
    array(
     'test' => 'have', 
     'this' => 'fun', 
     'thing' => '' 
    ) 
); 

Je veux une sortie comme ça, notez que la valeur CSV est dynamique.

+0

La dernière ligne des données CSV doit-elle avoir une autre virgule? Ne semble pas être une donnée CSV valide si les lignes n'ont pas toutes le même nombre de colonnes. Ou le code doit-il tenir compte de ce nombre variable de colonnes? – Wiseguy

+0

son semblable, la première rangée serait les clés d'un tableau alors que d'autres sont sa valeur. sur la partie 'chose' => '', c'est correct. – PinoyStackOverflower

+0

Je comprends cela, mais la dernière ligne de données CSV est 'have, fun', qui a seulement deux colonnes, pas trois comme les autres lignes. Devons-nous tenir compte des lignes qui ont le mauvais nombre de colonnes comme ça? – Wiseguy

Répondre

33

En supposant chaque ligne dans les données CSV a le même nombre de colonnes, cela devrait fonctionner.

$lines = explode("\n", $csv_data); 
$head = str_getcsv(array_shift($lines)); 

$array = array(); 
foreach ($lines as $line) { 
    $array[] = array_combine($head, str_getcsv($line)); 
} 

Si les lignes ont un nombre variable de colonnes (comme dans votre exemple, où la dernière ligne a 2 colonnes au lieu de 3), utilisez cette boucle à la place:

foreach ($lines as $line) { 
    $row = array_pad(str_getcsv($line), count($head), ''); 
    $array[] = array_combine($head, $row); 
} 
+1

Et qu'en est-il des données csv qui contiennent \ n dans des champs uniques. La notation habituelle dans csv est d'entourer de tels champs avec des guillemets, par ex. "une certaine valeur \ nin un champ". Donc, ceux-ci doivent être ignorés lors de l'analyse. Votre approche explosive les coupera. –

+0

@ChrisPillen Bien que n'étant pas l'une des exigences du demandeur, c'est un point valide. Que pensez-vous que le meilleur remède pour cela serait? Sauvegardez les données CSV dans un ['tmpfile()'] (http://php.net/tmpfile) et analysez-le en utilisant ['fgetcsv()'] (http://php.net/fgetcsv)? Devrais-je ajouter un exemple de cela à ma réponse? – Wiseguy

+0

@Wiseguy Vous pouvez utiliser regex pour analyser les données, mais en utilisant un fichier temporaire et 'fgetcsv()' serait le plus simple et beaucoup plus propre. –

4

Voici une solution complète:

$lines = explode("\n", $csv_data); 
$formatting = explode(",", $lines[0]); 
unset($lines[0]); 
$results = array(); 
foreach ($lines as $line) { 
    $parsedLine = str_getcsv($line, ','); 
    $result = array(); 
    foreach ($formatting as $index => $caption) { 
     if(isset($parsedLine[$index])) { 
     $result[$formatting[$index]] = trim($parsedLine[$index]); 
     } else { 
     $result[$formatting[$index]] = ''; 
     } 
    } 
    $results[] = $result; 
} 

Alors, que faisons-nous ici?

  • Tout d'abord, vos données CSV est divisé en réseau de lignes avec explode
  • Depuis la première ligne de votre CSV décrit le format de données, il doit être séparé des lignes de données réelles (explode et unset)
  • Pour stocker les résultats, nous initialisons un nouveau tableau ($results)
  • Foreach est utilisé pour parcourir la ligne de données ligne par ligne. Pour chaque ligne:
    • ligne est analysé avec str_getcsv PHP
    • Un tableau de résultats vide est initialisé
    • Chaque ligne est inspecté à la lumière du format. Les cellules sont ajoutées et les colonnes manquantes sont complétées avec des chaînes vides.
+0

Il ne sort pas correctement que je voulais, merci \ pour votre réponse :) – PinoyStackOverflower

+0

Il était problème beaucoup plus complexe que je pensais. Vérifiez la réponse révisée. L'explication détaillée suivra. – jsalonen

+0

Explication ajoutée. Compte tenu de votre description, cela devrait répondre à la question. – jsalonen

2

Voici une solution très propre et simple:

function parse_row($row) { 
    return array_map('trim', explode(',', $row)); 
} 

$rows = str_getcsv($csv_data, "\n"); 
$keys = parse_row(array_shift($rows)); 
$result = array(); 

foreach ($rows as $row) { 
    $row = parse_row($row); 
    $row = array_pad($row, 3, NULL); 

    $result[] = array_combine($keys, $row); 
} 
Questions connexes