4 Stimmen

Erhalte alle Array-Schlüssel nach Wert

Sagen wir, ich habe ein Array wie dieses:

Array
(
[Start] => Array
    (
        [Item 1] => Array
            (
                [0] => Item 1_1
                [Item 2_1] => Array
                    (
                        [Item 2_1_1] => x
                    )

                [1] => Item 3_1
            )

        [0] => Item 2
        [1] => Item 3
    )

)

Gibt es eine PHP-Funktion, die ich verwenden kann, um den Pfad zu erhalten, der zum Wert x in meinem Array führt, in diesem Fall wäre das Ergebnis folgendes:

Start, Item 1, Item 2_1, Item 2_1_1, x

2voto

Anh Nhan Nguyen Punkte 318

Die einzige Methode, die mir momentan einfällt, wäre eine Vielzahl von verschachtelten foreach ($array as $key => $value)-Schleifen zusammen mit array_search().

Es wäre jedoch besser, es als rekursive Methode zu gestalten, daher wäre es klug, eine Funktion zu verwenden.

function recursiveSearch($key, $array)
{
    foreach ($array as $k => $ar) {
        if (is_array('x', $ar)) {
            return $k . ', ' . array_search('x', $ar);
        } else {
            if ($ar === 'x') {
                return $k
            } else {
                return recursiveSearch($key, $ar);
            }
        }
    }
}

Nur ein Ansatz, der nicht unbedingt funktioniert oder so etwas in der Art.

2voto

hakre Punkte 184133

Das Problem, das Sie haben, betrifft Rekursion und/oder Baumtraversierung. PHP unterstützt die Baumtraversierung eines Arrays mit dem RecursiveArrayIterator und RecursiveIteratorIterator.

Um alle Schlüssel aller Elternarrays zu erhalten, müssen Sie von der ersten Ebene bis zur aktuellen Tiefe gehen und die Schlüssel erhalten. Dies wird auch vom RecursiveIteratorIterator mit der Methode getSubIterator() unterstützt. Es ist im Handbuch nicht wirklich gut dokumentiert, daher hier ein Beispiel:

$it = new RecursiveIteratorIterator(
    new RecursiveArrayIterator($array)
);

foreach ($it as $value) {
    if ($value !== 'x') continue;

    $keys  = array();
    $depth = $it->getDepth();
    for ($i = 0; $keys[] = $it->getSubIterator($i)->key(), $depth--; $i++);

    echo implode(', ', $keys), ', ', $value, "\n";
}

In diesem Beispiel wird zunächst der RecursiveArrayIterator mit Ihrem $array erstellt. Um die Baumtraversierung zu aktivieren, wird er in den RecursiveIteratorIterator eingewickelt. Dies ist notwendig, um den $it-Iterator rekursiv mit dem foreach zu verwenden.

Im foreach wird dann der Arraywert gegen Ihren Suchwert überprüft. Wenn er nicht übereinstimmt, wird mit dem nächsten Wert fortgefahren.

Wenn er jedoch übereinstimmt, werden die Methoden getDepth() und getSubIterator() des rekursiven Iterators verwendet, um das Schlüsselarray zu erstellen.

Das Beispiel gibt folgende Ausgabe aus:

 Start, Element 1, Element 2_1, Element 2_1_1, x

Was Ihrer Beschreibung in der Frage entspricht.

Weil es sich um Iteratoren handelt, können Sie das auch in eine eigene Klasse implementieren. Die folgende Iterator-Klasse ermöglicht nicht nur die Baumtraversierung über das im Konstruktor bereitgestellte Array, sondern hat auch eine Methode namens getKeys(), die ein Array mit allen Schlüsseln vom niedrigsten Level bis zur aktuellen Tiefe zurückgibt:

/**
 * Klasse ArrayRecursiveKeysIterator
 */
class ArrayRecursiveKeysIterator extends RecursiveIteratorIterator
{
    /**
     * @param array $array
     */
    public function __construct(array $array)
    {
        parent::__construct(new RecursiveArrayIterator($array));
    }

    /**
     * @return array Schlüssel
     */
    public function getKeys()
    {
        for ($k = [], $i = 0, $m = $this->getDepth(); $i <= $m; $i++)
            $k[] = $this->getSubIterator($i)->key();
        return $k;
    }
}

Es ist dann einfacher zu verwenden (und wahrscheinlich auch für andere Szenarien). Ein einfaches Anwendungsbeispiel zuerst. Gehen Sie durch das Array und zeigen Sie alle Schlüssel für jeden Wert an. Instantiieren Sie den Iterator für Ihr Array und geben Sie die Schlüssel für jeden Wert aus:

$it = new ArrayRecursiveKeysIterator($array);
foreach ($it as $value) {
    echo implode(', ', $it->getKeys()), ', ', $value, "\n";
}

Dies erzeugt die folgende Ausgabe:

Start, Element 1, 0, Element 1_1
Start, Element 1, Element 2_1, Element 2_1_1, x
Start, Element 1, 1, Element 3_1
Start, 0, Element 2
Start, 1, Element 3

In Ihrem Szenario möchten Sie den Iterator auch basierend auf einem bestimmten Wert filtern (hier der Zeichenkette "x"), was Sie ganz einfach durch die Verwendung des RegexIterator, der ein FilterIterator ist, tun können. Hier ist also Ihr Szenario:

$it     = new ArrayRecursiveKeysIterator($array);
$filter = new RegexIterator($it, '~^x$~');
foreach ($filter as $value) {
    echo implode(', ', $it->getKeys()), ', ', $value, "\n";
}

Und hier die Ausgabe:

Start, Element 1, Element 2_1, Element 2_1_1, x

Wie Sie sehen können, ist es nach dem Wert gefiltert, an dem Sie interessiert sind.

Weitere zugehörige Fragen, an denen Sie wahrscheinlich interessiert sind, sind:

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X