2012-02-21 20 views
6

Ho provato ad accorciare la mia domanda, ma questo è il meglio che potrei fare. Dal Credo che sia piuttosto difficile da capire che cosa ho bisogno, fornirò un esempio:Il modo più efficace per rilevare e rimuovere elementi nell'array in base al valore e all'ultimo valore degli elementi

Dire che ho il seguente array:

$var = array(
    array(1, 2, 3), 
    array(1, 3), 
    array(1, 2, 4, 3), 
    array(1, 3, 4) 
); 

Quello che voglio è quello di rimuovere tutte le matrici da $var che hanno la il primo e l'ultimo elemento sono gli stessi di un altro array da $var ma hanno più elementi rispetto al secondo.

Quindi, le seguenti matrici deve essere rimosso: (1, 2, 3) e (1, 2, 4, 3) perché entrambi iniziare e terminare con 13 e avere più elementi di (1, 3), che inizia e termina anche con 1 e 3. (1, 3, 4) dovrebbe rimanere, perché non c'è nessun altro array che inizia con 1 e termina con 4 e ha meno elementi di esso.

Sto cercando il modo più efficiente per farlo, sia in termini di memoria che di tempo. $var può contenere fino a 100 matrici e ogni singolo array può contenere fino a 10 elementi. Ho pensato di utilizzare una sorta di confronto tra tutti e due gli elementi (for(i=0;...) for(j=i+1;...) complexCompareFunction();), ma credo che non sia molto efficiente.

+0

Avete un caso d'uso per quello che stai cercando di fare? Potrebbe esserci un modo migliore per implementarlo ... – Josh

+2

Sto generando tutte le combinazioni di linee di trasporto pubblico che collegano due posizioni selezionate dall'utente. Dalla serie di combinazioni di linee generate ('$ var' in questo caso), vorrei eliminare quelle che usano una linea aggiuntiva. Quindi, se si può raggiungere il secondo punto con le righe '(1, 3)', perché dovrebbe essere visualizzato anche '(1, 2, 3)'? Qui, la riga '2' è extra, si può raggiungere la destinazione senza di essa. – linkyndy

+0

forse viaggiare 1,2,3 richiederà meno tempo (perché vai in treno) di 1,3 (perché puoi andare solo in autobus direttamente). potremmo ricostruire il problema: avere un grafico con stazioni come nodi e connessioni come bordi. per ogni due nodi n, m ora cerchi il percorso più breve che inizia con n e termina con m. ci sono tonnellate di riferimenti là fuori su questo argomento. – Basti

risposta

1

In generale, sì, sei troppo preoccupato per l'efficienza (come ti sei chiesto in un altro commento). Sebbene PHP non sia il linguaggio più blasonante, suggerirei di creare la soluzione più semplice, e solo preoccuparmi di ottimizzarlo o renderlo più efficiente se c'è un problema evidente con il risultato finale.

Ecco cosa vorrei fare, in cima alla mia testa. Essa si basa off di risposta di ajreal ma si spera sarà più facile da seguire, e prendere alcuni casi limite che quella risposta senza risposta:

// Assume $var is the array specified in your question 

function removeRedundantRoutes($var){ 

    // This line sorts $var by the length of each route 
    usort($var, function($x, $y){ return count($x) - count($y); }); 

    // Create an empty array to store the result in 
    $results = array(); 

    // Check each member of $var 
    foreach($var as $route){ 
     $first = $route[0]; 
     $last = $route[ count($route) - 1 ]; 
     if(!array_key_exists("$first-$last", $results)){ 
      // If we have not seen a route with this pair of endpoints already, 
      // it must be the shortest such route, so place it in the results array 
      $results[ "$first-$last" ] = $route; 
     } 
    } 

    // Strictly speaking this call to array_values is unnecessary, but 
    // it would eliminate the unusual indexes from the result array 
    return array_values($results); 
} 
+0

Con alcune modifiche, ho funzionato. Grazie per il vostro aiuto e per i dettagli nella risposta! – linkyndy

2

uso current e end

$all = array(); 
foreach ($var as $idx=>$arr): 
    $first = current($arr); 
    $last = end($arr); 
    $size = count($arr); 
    $key = $first.'.'.$last; 
    if (isset($all[$key])): 
    if ($size > $all[$key]): 
     unset($var[$idx]); 
    else: 
     $all[$key] = $size; 
    endif; 
    else: 
    $all[$key] = $size; 
    endif; 
endforeach; 

ops ... si può iterare (nuovo) alla fine di garantire la matrice di dimensioni già ridotto può essere ulteriormente rimosso

+0

In questo esempio, '(1, 2, 3)' esiste ancora nell'array. –

+0

Il codice funziona alla grande, ma solo se gli array all'interno di '$ var' sono ordinati per numero di elementi. Credo che non sarebbe molto efficiente ordinare prima il numero di elementi di $ var per matrici, e quindi eseguire il codice che hai postato. O sono troppo preoccupato per l'efficienza? – linkyndy

+0

Memorizza $ idx per la dimensione più piccola in $ all o un altro array e aggiungi unset per questo $ idx all'interno del resto. – piotrm

Problemi correlati