2010-08-10 14 views
40

ho incontrato una vecchia applicazione che utilizza un id al tipo di nome di matrice, per esempio ...Come posso forzare PHP a utilizzare le stringhe per le chiavi di array?

array(1) { 
    [280]=> 
    string(3) "abc" 
} 

Ora ho bisogno di riordinare questi, e un var_dump() sarebbe far credere che questo non è succederà mentre le chiavi sono numeri interi.

Se posso aggiungere un a per ogni indice, var_dump() mostrerà virgolette intorno alla chiave, la mia ipotesi per dimostrare che è ormai una stringa ...

array(1) { 
    ["280a"]=> 
    string(3) "abc" 
} 

Questo mi lascerebbe facilmente riordinare, senza dover toccare più codice.

Questo non funziona non funziona.

$newArray = array(); 
foreach($array as $key => $value) { 
    $newArray[(string) $key] = $value; 
} 

Un var_dump() essi mostra ancora come indici di matrice interi.

C'è un modo per forzare le chiavi ad essere stringhe, quindi posso riordinarle senza rovinare l'array?

+0

Aveva lo stesso problema. Ho ottenuto chiavi come "0", "1" nei dati di input (dalla richiesta http) e volevo filtrarle usando 'array_intersect_key' ... sembra che userò un altro approccio. – kirilloid

+0

Possibile duplicato di [Una stringa numerica come chiave di array in PHP] (http://stackoverflow.com/questions/4100488/a-numeric-string-as-array-key-in-php) – Flimm

+0

@Flimm Quella domanda è stata posta dopo il mio, quindi è un duplicato di questo. – alex

risposta

7

EDIT:

pensai che se sono numeri interi, io posso non li riordino senza cambiare la chiave (che è significativa in questo esempio). Tuttavia, se fossero stringhe , posso riordinarle come sono come l'indice non dovrebbe essere interpretato per avere un significato speciale . Ad ogni modo, vedi l'aggiornamento alla mia domanda per come l'ho fatto (sono andato su un percorso diverso ).

In realtà essi non dovete essere in ordine numerico ...

array(208=>'a', 0=> 'b', 99=>'c'); 

è perfettamente valida se sei assegnandole manualmente. Anche se sono d'accordo che le chiavi intere potrebbero essere interpretate erroneamente come aventi un significato sequenziale da parte di qualcuno, anche se si penserebbe che se fossero in un ordine non numerico sarebbe evidente che non lo fossero. Detto questo, penso che dal momento che hai avuto il margine di manovra per cambiare il codice mentre ti aggiorni, questo è l'approccio migliore.


non

Probabilmente il modo più efficiente, ma un gioco da ragazzi:

$keys = array_keys($data); 

$values = array_values($data); 
$stringKeys = array_map('strval', $keys); 

$data = array_combine($stringKeys, $values); 

//sort your data 
+0

Gli argomenti 'array_map' sono nel modo sbagliato. Provalo ora, grazie. – alex

+0

Scusate, non l'ho menzionato, ma questo è su un progetto PHP4 quindi no 'array_combine()'. Mi limiterò a scorrere e costruirò. – alex

+1

Bummer, non ha funzionato. Sembrano essere restituiti all'intero. Ho anche provato a usare l'operatore cast '(string)'. Non è fino a quando non aggiungo un numero intero che si trasforma in stringa. – alex

9

come su questo?

$newArray = array(); 
foreach($oldArray as $key => $value) { 
    $newArray[$key.''] = $value; 
} 

edit: provato anche questo e sì, non ha funzionato.

Dal PHP docs:

Una chiave può essere un numero intero o una stringa .Se una chiave è la rappresentazione standard di di un numero intero, sarà interpretata come tale (ad esempio "8" sarà interpretata come 8, mentre "08" sarà interpretata come "08"). I float nella chiave vengono troncati all'intero. Non ci sono diversi tipi di array indicizzati e associati in PHP; c'è solo un tipo di array , che può contenere entrambi gli indici interi e stringhe .

Immagino che ora dipenda da come si desidera ordinare l'array. (Output finale?)

+3

Sfortunatamente, ho provato [http://codepad.org/1IqwfZUx] e non funziona. Grazie per essere passato da Andy! – alex

+0

sì come si desidera ordinare esattamente l'array? – prodigitalson

+0

@prodigitalson Ho assunto che se sono interi, non posso riordinarli senza cambiare la chiave (che è significativa in questo esempio). Tuttavia, se fossero stringhe, posso riordinarle come preferiscono in quanto l'indice non deve essere interpretato in modo da avere un significato speciale. Ad ogni modo, vedi il mio aggiornamento di domande per come l'ho fatto (sono andato lungo una strada diversa). – alex

1

Edit: Questo dovrebbe funzionare

foreach($array as $key => $value) { 
    $newkey = sprintf('%s',$key); 
    $newArray["'$newkey'"] = $value; 
} 
+1

Interessante, ma questo aggiunge solo più complessità, credo. – alex

+0

Dai un'occhiata alla modifica ... Penso che questo dovrebbe funzionare. – user387302

+0

In realtà ora che ci penso, anche questo potrebbe funzionare: $ newArray ["'$ chiave'"] = $ valore – user387302

6

Utilizzare un oggetto invece di un array $object = (object)$array;

+0

@ ÁlvaroGonzález puoi iterare qualsiasi oggetto proprio come un array, no? Passerà attraverso le proprietà disponibili nell'ambito di chiamata. – nawfal

+0

@nawfal - Hai ragione, ottieni automaticamente tutte le proprietà pubbliche. Non ero a conoscenza di quella caratteristica. Toglierò il mio commento per evitare di diffondere confusione. Grazie per il puntatore. –

3

sono stato in grado di ottenere questo al lavoro con l'aggiunta di' 0,0' sul fine di ogni tasto, in quanto tale:

$options = []; 
for ($i = 1; $i <= 4; $i++) { 
    $options[$i.'.0'] = $i; 
} 

tornerà:

array("1.0" => 1, "2.0" => 2, "3.0" => 3, "4.0" => 4)

Potrebbe non essere completamente ottimale ma consente di ordinare l'array ed estrarre (un equivalente della) chiave originale senza dover troncare nulla.

+0

potrebbe essere abbastanza buono per alcuni casi d'uso. – ahnbizcad

6

NON PUOI !!

Le stringhe contenenti interi validi verranno convertite nel tipo intero. Per esempio. il tasto "8" verrà effettivamente memorizzato sotto 8. D'altra parte "08" non verrà lanciato, in quanto non è un numero intero decimale valido.

Edit:

In realtà si può !! Cast sequential array to associative array

$obj = new stdClass; 
foreach($array as $key => $value){ 
    $obj->{$key} = $value; 
} 
$array = (array) $obj; 

Nella maggior parte dei casi, la seguente citazione vero.

Le stringhe contenenti numeri interi validi verranno convertite nel tipo intero. Per esempio. il tasto "8" verrà effettivamente memorizzato sotto 8. D'altra parte "08" non verrà lanciato, in quanto non è un numero intero decimale valido.

Questo esempio dal PHP Docs

<?php 
    $array = array(
     1 => "a", 
     "1" => "b", 
     1.5 => "c", 
     true => "d", 
    ); 
    var_dump($array); 
?> 

Il precedente esempio visualizzerà:

array(1) { 
    [1]=> string(1) "d" 
} 

Quindi, anche se si dovesse creare un array con le chiavi numerate avrebbero solo ottenere colate indietro a numeri interi.

Sfortunatamente per me non ne ero a conoscenza fino a poco tempo fa, ma pensavo di condividere i miei tentativi falliti.

tentativi falliti

$arr = array_​change_​key_​case($arr); // worth a try. 

Restituisce un array con tutte le chiavi di matrice maiuscolo o in minuscolo. Gli indici numerati sono lasciati come è.

I miei prossimi tentativi erano di creare un nuovo array per array_combine inserendo i vecchi valori le nuove chiavi (stringa).

Ho provato diversi modi per rendere l'array $keys contenente valori numerici di tipo stringa.

range("A", "Z") funziona per l'alfabeto, quindi mi piacerebbe provarlo con una stringa numerica.

$keys = range("0", (string) count($arr)); // integers 

Ciò ha provocato un array pieno di chiavi, ma erano tutte di tipo int.

Ecco un paio di tentativi riusciti di creare un array con i valori di tipo stringa.

$keys = explode(',', implode(",", array_keys($arr))); // values strings 

$keys = array_map('strval', array_keys($arr)); // values strings 

Ora solo per combinare i due.

$arr = array_combine($keys, $arr); 

Questo è quando ho scoperto stringhe numeriche casted a numeri interi.

$arr = array_combine($keys, $arr); // int strings 
//assert($arr === array_values($arr)) // true. 

L'unico modo per cambiare le chiavi in ​​stringhe e mantenere i loro valori letterali sarebbe quello di anteporre la chiave con un suffisso con un punto decimale "00","01","02" o "0.","1.","2.".

È possibile ottenere questo come tale.

$keys = explode(',', implode(".,", array_keys($arr)) . '.'); // added decimal point 
$arr = array_combine($keys, $arr); 

Ovviamente questo non è l'ideale in quanto sarà necessario indirizzare elementi di array come questo.

$arr["280."] 

ho creato un po 'di funzione che ha per obiettivo l'elemento di matrice corretta anche se si immette solo il numero intero e non la nuova stringa.

function array_value($array, $key){ 

    if(array_key_exists($key, $array)){ 
     return $array[ $key ]; 
    } 
    if(is_numeric($key) && array_key_exists('.' . $key, $array)){ 
     return $array[ '.' . $key ]; 
    } 
    return null; 
} 

Uso

echo array_value($array, "208"); // "abc" 

Edit:

In realtà si può !! Cast sequential array to associative array

Tutto questo per niente

3

È possibile aggiungere il carattere null "\0" alla fine la chiave dell'array. Questo rende così PHP non può interpretare la stringa come un intero. Tutte le funzioni dell'array (come array_merge()) funzionano su di esso. Inoltre, nemmeno lo var_dump() mostrerà qualcosa in più dopo la stringa di numeri interi.

Esempio:

$numbers1 = array(); 
$numbers2 = array(); 
$numbers = array(); 

$pool1 = array(111, 222, 333, 444); 
$pool2 = array(555, 666, 777, 888); 

foreach($pool1 as $p1) 
{ 
    $numbers1[$p1 . "\0"] = $p1; 
} 
foreach($pool2 as $p2) 
{ 
    $numbers2[$p2 . "\0"] = $p2; 
} 

$numbers = array_merge($numbers1, $numbers2); 

var_dump($numbers); 

L'uscita risultante sarà:

array(8) { 
    ["111"] => string(3) "111" 
    ["222"] => string(3) "222" 
    ["333"] => string(3) "333" 
    ["444"] => string(3) "444" 
    ["555"] => string(3) "555" 
    ["666"] => string(3) "666" 
    ["777"] => string(3) "777" 
    ["888"] => string(3) "888" 
} 

Senza la parte . "\0" matrice risultante sarebbe:

array(8) { 
    [0] => string(3) "111" 
    [1] => string(3) "222" 
    [2] => string(3) "333" 
    [3] => string(3) "444" 
    [4] => string(3) "555" 
    [5] => string(3) "666" 
    [6] => string(3) "777" 
    [7] => string(3) "888" 
} 

anche ksort() sarà anche ignorare il nullo carattere significato $numbers[111] e $numbers["111\0"] avranno entrambi lo stesso peso nell'algoritmo di ordinamento.

L'unico inconveniente di questo metodo è che per accedere, ad esempio $numbers["444"], si sarebbe effettivamente necessario accedervi tramite $numbers["444\0"] e dal momento che nemmeno var_dump() vi mostrerà non c'è un carattere null alla fine, non c'è alcun indizio sul perché ottieni "Offset non definito". Quindi usa questo trucco solo se iterando tramite foreach() o chi finisce per mantenere il tuo codice ti odierà.

-1

Solo un commentatore ha ragione, e la risposta accettata è errata. asort(), uasort() e arsort() sono incorporati negli array di ordinamento mantenendo le associazioni chiave e sono esistiti dalla versione 4. RTFM, persone.

Problemi correlati