PHP : inverser deux valeurs d'un array

Bonjour,

Pour un array donné, je veux inverser deux valeurs…

Le tableau est de ce style :

array(1) { [0]=> array(11) { [0]=> string(11) "BEGIN:VCARD" [1]=> string(40) "PRODID:-//Sabre//Sabre VObject 4.1.2//EN" [2]=> string(40) "UID:eacbcff5-29d6-4ea4-b8ee-70dffd3b650a6" [3]=> string(18) "CATEGORIES:Amis" [4]=> string(25) "N:Monde;Marie;;;" [5]=> string(24) "FN:Marie Monde;" [6]=> string(20) "REV:20180325T202333Z" [7]=> string(26) "TEL;TYPE=CELL:+33666123456" [8]=> string(41) "EMAIL;TYPE=HOME:email@domain.tld" [9]=> string(11) "VERSION:3.0" [10]=> string(9) "END:VCARD" } }

Je cherche en premier la position de la valeur contenant le mot “VERSION”.

                   if(stripos($value, "VERSION") === 0) {
                        if($key != 1) {
                            $index = array_search($value, $array);
                        } else {
                            $index = $key;
                        }
                    }

J’ai besoin de mettre la valeur contenant “VERSION”, à l’index 1, et que les index suivants bougent en conséquence : le 1 à la place du 2, le 2 à celle du 3, etc… Comment faire ?!


J’ai bien “écrit” ces deux fonctions, mais je n’y arrive pas :

function swap_array($haystack,$key1,$key2) {
   $tmp = $haystack[$key1];
   $haystack[$key1] = $haystack[$key2];
   $haystack[$key2] = $tmp;
 
    return $haystack;  
}


function switch_keys($key1, $key2, $haystack) {
  if ($key1 > $key2) {
    $tmp = $key1;
    $key1 = $key2;
    $key2 = $tmp;
  }
  for ($i = $key1; $i < $key2; $i -= 1) {
    return swap_array($haystack,$i,$key2);
  }
}

Elles permettent de ré-empiler les index correctement.


Votre idée ?!

Bonjour,

Tu utilises la fonction stripos qui cherche dans une chaine de caractère, donc déjà ça ne fonctionne pas. Tu l’aurais vu en appliquant ta fonctionne sans la tester :

echo stripos($array, "VERSION"); // résultat : stripos() expects parameter 1 to be string, array given

J’ai reproduit ton tableau comme ceci :

$array = array(
    0 => array(
        "BEGIN:VCARD",
        "PRODID:-//Sabre//Sabre VObject 4.1.2//EN",
        "UID:eacbcff5-29d6-4ea4-b8ee-70dffd3b650a6",
        "CATEGORIES:Amis",
        "N:Monde;Marie;;;",
        "FN:Marie Monde;",
        "REV:20180325T202333Z",
        "TEL;TYPE=CELL:+33666123456",
        "EMAIL;TYPE=HOME:email@domain.tld",
        "VERSION:3.0",
        "END:VCARD"
    )
);

Pour rechercher dans un tableau, il faut utiliser array_search.

Maintenant, ton tableau contient un tableau, tu ne peux donc pas directement chercher dedans. De plus, tu cherche une chaine de caractère commençant par, et non étant exactement. Il faut donc parcourir l’ensemble des éléments du tableau pour chercher dedans.

/** Parcourir le tableau secondaire **/
foreach ($array[0] as $key => $value) {
    /** SI la valeur contient "VERSION", alors stocker sa position **/
    if (strstr($value, "VERSION")) {
        /* Stocker la position */
        $versionPos = $key;
        
        echo $versionPos;
        
        // Faire la transformation sur un tableau temporaire
        
        /* Sortir */
        break;
    }
}

Je suis pas super fort, mais je verrais bien ça:

$lastval="";
foreach ($array as $line) {
    foreach ($line as $idx => $value) {
        if (strstr($value, "VERSION")) {
            $line[0]=$value;
            if($idx>=0) {$line[$idx]=$lastval; };
            break;
        } else {
            $line[$idx]=$lastval;
            $lastval=$value;
        };
    };
};

Beh, si ça fonctionne !

Justement l’usage du test avec l’opérateur ‘===’ sur 0, permet de trouver non seulement la chaine de caractère, mais en plus à la position 0.
Je te renvoie à la documentation PHP sur strpos et particulièrement ce comment… et, pour le tester plus d’une fois dans mon code, je confirme que ça fonctionne !

Mon problème n’est pas la détection de ma chaîne, c’est bel et bien l’inversion des deux valeurs, ni + ni - !

Mon code actuel :

$cntnt = [];
            foreach($contenu as $k1 => $val) {

                foreach($contenu[$k1] as $key => $value) {
                    //var_dump($key, $value);
                    if(stripos($value, "VERSION") === 0) {
                        if($key != 1) {
                            $index = array_search($value, $contenu[$k1]);
                            var_dump($index);
                        } else {
                            $index = $key;
                        }
                    }
                    
                    $cntnt[$k1][$key] = $value;
                    
                }
                unset($key, $value);
                
                if($index != 1) switch_keys( 1, $index, $cntnt[$k1] );
                
            }
            unset($content);

Je peux te garantir qu’il affiche bel et bien la valeur d’index !!

L’exemple typique du type de mauvaise fois…
Tu nous donnes dans ton premier poste uniquement ton tableau et une fonction de test qui contient stripos. Je réaffirme qu’on ne peut pas utiliser stripos sur un tableau !

En revanche, avec ton code actuel, évidemment que cela fonctionne !

Je suis agacé donc je lâche ce sujet, désolé.

Non, toi : relis ce que j’ai écris !!!

Pardon ???
Merci de ta gentillesse et de te permettre de me juger si vite !!!

Alors, je me suis peut-être mal exprimé dans mon premier post, mais ton avis péremptoire m’a agacé autant ni + ni - !
tu remarqueras que dans ma réponse, j’ai clairement évité de t’agresser alors que j’étais agacé par ta réponse péremptoire

Et, si je n’ai pas donné le code PHP sur le tableau, c’est parce que je me suis dit qu’il n’y en avait pas besoin.
Dernièrement, quand j’affirme quelque chose, c’est que je sais avoir raison…

Tu t’es focalisé sur un problème qui n’existait pas, et n’existe pas pour moi !


Alors, au lieu de m’agresser publiquement, si tu étais constructif - ce que je m’efforce d’être, malgré le fait d’être sous morphine à cause de la douleur - je pourrais peut-être arrivé à un résultat probant !

Je répète mon problème est bel et bien l’inversion des deux index|clés… merci d’en rester là !

@mattotop:
Avec ton code malheureusement je n’y arrive pas plus :

affichage array avant traitement:
array(1) { [0]=> array(11) { [0]=> string(11) "BEGIN:VCARD" [1]=> string(40) "PRODID:-//Sabre//Sabre VObject 4.1.2//EN" [2]=> string(39) "UID:eacbcff5-29d6-4ea4-b8ee-70dfedd50a6" [3]=> string(15) "CATEGORIES:Amis" [4]=> string(16) "N:Monde;Marie;;;" [5]=> string(15) "FN:Marie Monde;" [6]=> string(20) "REV:20180325T202333Z" [7]=> string(26) "TEL;TYPE=CELL:+33666123456" [8]=> string(32) "EMAIL;TYPE=HOME:email@domain.tld" [9]=> string(11) "VERSION:3.0" [10]=> string(9) "END:VCARD" } } 

affichage array après traitement:
array(1) { [0]=> array(11) { [0]=> string(11) "BEGIN:VCARD" [1]=> string(40) "PRODID:-//Sabre//Sabre VObject 4.1.2//EN" [2]=> string(39) "UID:eacbcff5-29d6-4ea4-b8ee-70dfedd50a6" [3]=> string(15) "CATEGORIES:Amis" [4]=> string(16) "N:Monde;Marie;;;" [5]=> string(15) "FN:Marie Monde;" [6]=> string(20) "REV:20180325T202333Z" [7]=> string(26) "TEL;TYPE=CELL:+33666123456" [8]=> string(32) "EMAIL;TYPE=HOME:email@domain.tld" [9]=> string(11) "VERSION:3.0" [10]=> string(9) "END:VCARD" } } 

On voit bien qu’il n’y a pas de permutation ! :frowning:

La discussion qu’on a en privé m’a fait revenir, voilà ce que j’ai pondu et qui semble fonctionner :

<?php
    /* Tableau d'entrée */
    $array = array(
        0 => array(
            "BEGIN:VCARD",
            "PRODID:-//Sabre//Sabre VObject 4.1.2//EN",
            "UID:eacbcff5-29d6-4ea4-b8ee-70dffd3b650a6",
            "CATEGORIES:Amis",
            "N:Monde;Marie;;;",
            "FN:Marie Monde;",
            "REV:20180325T202333Z",
            "TEL;TYPE=CELL:+33666123456",
            "EMAIL;TYPE=HOME:email@domain.tld",
            "VERSION:3.0",
            "END:VCARD"
        )
    );
    
    /* Tableau de sortie */
    $arrayOut = array();

    /** Parcourir le premier niveau **/
    foreach ($array as $levelOneKey => $levelOneValue) {
        /** Parcourir le deuxième niveau **/
        foreach ($levelOneValue as $key => $value) {
            /** SI la valeur contient "VERSION", alors stocker en index 1 **/
            if (strstr($value, "VERSION")) {
                $arrayOut[$levelOneKey][1] = $array[$levelOneKey][$key];
            }
            /** SINON SI l'index est suppérieur à 1, alors faire +1 et stocker **/
            elseif ($key >= 1) {
                $arrayOut[$levelOneKey][$key++] = $value;
            }
            else {
                $arrayOut[$levelOneKey][] = $value;
            }
        }
    }

    echo "<pre>";
        var_dump($array);
        var_dump($arrayOut);
    echo "</pre>";

C’est pas élégant, mais bon, ça fait le travail.

suis entrain de tester ton code… je te tiens informé ! :wink:

Bon, j’ai forcèment adapté ton code :

echo "affichage array avant traitement:";
            var_dump($contenu); 

            $cntnt = [];  //$lastval='';
            
            foreach ($contenu as $levelOneKey => $levelOneValue) {
        /** Parcourir le deuxième niveau **/
        foreach ($levelOneValue as $key => $value) {
            /** SI la valeur contient "VERSION", alors stocker en index 1 **/
            if (strstr($value, "VERSION")) {
                $cntnt[$levelOneKey][1] = $contenu[$levelOneKey][$key];
            }
            /** SINON SI l'index est suppérieur à 1, alors faire +1 et stocker **/
            elseif ($key >= 1) {
                $cntnt[$levelOneKey][$key++] = $value;
            }
            else {
                $cntnt[$levelOneKey][] = $value;
            }
        }
    }

echo "affichage array après traitement:";
            var_dump($cntnt); 

Et ça me restitue :

affichage array avant traitement:
array(1) { [0]=> array(11) { 
 [0]=> string(11) "BEGIN:VCARD" 
 [1]=> string(40) "PRODID:-//Sabre//Sabre VObject 4.1.2//EN" 
 [2]=> string(39) "UID:eacbcff5-29d6-4ea4-b8ee-70dfedd50a6" 
 [3]=> string(15) "CATEGORIES:Amis" 
 [4]=> string(16) "N:Monde;Marie;;;" 
 [5]=> string(15) "FN:Marie Monde;" 
 [6]=> string(20) "REV:20180325T202333Z" 
 [7]=> string(26) "TEL;TYPE=CELL:+33666123456" 
 [8]=> string(32) "EMAIL;TYPE=HOME:email@domain.tld" 
 [9]=> string(11) "VERSION:3.0" 
[10]=> string(9) "END:VCARD" } } 
affichage array après traitement:
array(1) { [0]=> array(10) { 
 [0]=> string(11) "BEGIN:VCARD" 
 [1]=> string(11) "VERSION:3.0" 
 [2]=> string(39) "UID:eacbcff5-29d6-4ea4-b8ee-70dfedd50a6" 
 [3]=> string(15) "CATEGORIES:Amis" 
 [4]=> string(16) "N:Monde;Marie;;;" 
 [5]=> string(15) "FN:Marie Monde;" 
 [6]=> string(20) "REV:20180325T202333Z" 
 [7]=> string(26) "TEL;TYPE=CELL:+33666123456" 
 [8]=> string(32) "EMAIL;TYPE=HOME:email@domain.tld" 
[10]=> string(9) "END:VCARD" } } 

ça fonctionne correct… à un détail près est que l’ancienne valeur est détruite, hors il faut la garder…
mon propos est bien d’insérer la valeur de ‘VERSION’ à la clé 1, où que soit cette valeur, sauf si elle appartient bien à la clé 1, et de garder les autres valeurs.

Autant pour moi, je n’avais pas fait attention aux index. Ça c’est mieux :

<?php
	/* Tableau d'entrée */
	$array = array(
		0 => array(
			"BEGIN:VCARD",
			"PRODID:-//Sabre//Sabre VObject 4.1.2//EN",
			"UID:eacbcff5-29d6-4ea4-b8ee-70dffd3b650a6",
			"CATEGORIES:Amis",
			"N:Monde;Marie;;;",
			"FN:Marie Monde;",
			"REV:20180325T202333Z",
			"TEL;TYPE=CELL:+33666123456",
			"EMAIL;TYPE=HOME:email@domain.tld",
			"VERSION:3.0",
			"END:VCARD"
		)
	);
	
	/* Tableau de sortie */
	$arrayOut = array();

	/** Parcourir le premier niveau **/
	foreach ($array as $levelOneKey => $levelOneValue) {
		/** Parcourir le second niveau **/
		foreach ($levelOneValue as $levelTwoKey => $levelTwoValue) {
			/** SI la valeur contient ce qu'on cherche **/
			if (strstr($levelTwoValue, "VERSION")) {
				/* Stocker la position */
				$versionPos = $levelTwoKey;
				
				/* Interrompre */
				break;
			}
		}
		
		/* Conserver le premier index */
		$arrayOut[$levelOneKey][0] = $levelOneValue[0];
		
		/* Insérer la version en deuxième position */
		$arrayOut[$levelOneKey][1] = $levelOneValue[$versionPos];
		
		/* Supprimer les clefs déjà insérées */
		unset($levelOneValue[0]);
		unset($levelOneValue[$versionPos]);
		
		/* Ajouter dans le tableau de sortie le reste des valeurs */
		$arrayOut[$levelOneKey] = array_merge($arrayOut[$levelOneKey], $levelOneValue);
	}

	echo "<pre>";
		var_dump($array);
		var_dump($arrayOut);
	echo "</pre>";
1 J'aime

Merci beaucoup !
:smiley: :smiley: :smiley:

1 J'aime

@sk4hrr: Je tiens à te remercier, car ta version finale fonctionne vraiment bien, même quand le tableau principal renferme plusieurs autres enregistrements de type tableau !

Bon, ça c’est le cas où le fichier reçu, qui est injecté dans le tableau, est somme toute simple,- de type simple, tel que :

BEGIN:VCARD
PRODID:-//Sabre//Sabre VObject 4.1.2//EN
UID:eacbcff5-29d6-4ea4-b8ee-70dfedd50a6
VERSION:3.0
CATEGORIES:Amis
N:Monde;Joseph;;;
FN:Joseph Monde;
REV:20180325T202333Z
TEL;TYPE=CELL:+33777123456
EMAIL;TYPE=HOME:email@domain.tld
END:VCARD

Maintenant, imaginons qu’il soit un peu plus compliqué, parce que justement cela peut arriver, tel que :

BEGIN:VCARD
PRODID:-//Sabre//Sabre VObject 4.1.2//EN
UID:eacbcff5-29d6-4ea4-b8ee-70dfedd50a6
CATEGORIES:Amis
N:Monde;Marie;;;
FN:Marie Monde;
REV:20180325T202333Z
TEL;TYPE=CELL:+33666123456
EMAIL;TYPE=HOME:email@domain.tld
VERSION:3.0
KEY;ENCODING=b:MIICajCCAdOgAwIBAgICBEUwDQYJKoZIhvcNAQEEBQA
    wdzELMAkGA1UEBhMCVVMxLDAqBgNVBAoTI05ldHNjYXBlIENbW11bmljYX
    Rpb25zIENvcnBvcmF0aW9uMRwwGgYDVQQLExNJbmZvcm1hdGlvbiBTeXN0
    ZW1zMRwwGgYDVQQDExNyb290Y2EubmV0c2NhcGUuY29tMB4XDTk3MDYwNj
    E5NDc1OVoXDTk3MTIwMzE5NDc1OVowgYkxCzAJBgNVBAYTAlVTMSYwJAYD
    VQQKEx1OZXRzY2FwZSBDb21tdW5pY2F0aW9ucyBDb3JwLjEYMBYGA1UEAx
    MPVGltb3RoeSBBIEhvd2VzMSEwHwYJKoZIhvcNAQkBFhJob3dlc0BuZXRz
    Y2FwZS5jb20xFTATBgoJkiaJk/IsZAEBEwVob3dlczBcMA0GCSqGSIb3DQ
    EBAQUAA0sAMEgCQQC0JZf6wkg8pLMXHHCUvMfL5H6zjSk4vTTXZpYyrdN2
    dXcoX49LKiOmgeJSzoiFKHtLOIboyludF90CgqcxtwKnAgMBAAGjNjA0MB
    EGCWCGSAGG+EIBAQQEAwIAoDAfBgNVHSMEGDAWgBT84FToB/GV3jr3mcau
    +hUMbsQukjANBgkqhkiG9w0BAQQFAAOBgQBexv7o7mi3PLXadkmNP9LcIP
    mx93HGp0Kgyx1jIVMyNgsemeAwBM+MSlhMfcpbTrONwNjZYW8vJDSoi//y
    rZlVt9bJbs7MNYZVsyF1unsqaln4/vy6Uawfg8VUMk1U7jt8LYpo4YULU7
    UZHPYVUaSgVttImOHZIKi4hlPXBOhcUQ==
END:VCARD

Juste pour info : la clé est fausse !
Parce que, oui, dans certains contextes, tel que celui de ‘KEY’, il peut y avoir plusieurs lignes continues, commençant soit par une espace, soit par une tabulation.
Cela peut être le cas de tout autre contexte, tel que ‘NOTE’ - qui n’existe pas dans cet exemple - et qui est le premier qui me vient à l’esprit…


Je récupère le contenu du fichier ainsi - sachant que le reste du code, tu connais pour me l’avoir “corrigé” - :

$container = file($file_tmp, FILE_IGNORE_NEW_LINES); 
            $contenu = array();
            $i=0; $j=0;
            foreach($container as $contain) {
                if(!empty($contain)) {  
                    $contenu[$i][$j] = $contain;
                    if(stripos($contain, "END") === 0) { $i++; $j=0; }
                    else $j++;
                }
            }
            unset($key, $value);

La question que je me pose est : est-ce que je dois modifier ce code pour détecter si la ligne commence par une espace ou une tabulation, alors je dois l’intégrer en ajout de la valeur de l’index précédent… ou je m’y essaye après dans le traitement du tableau ???

Qu’en penses-tu ?