简体   繁体   中英

How can I filter an array of strings to remove elements that are prefixes of other elements?

If I have an array of strings, how can I reduce it by filtering out any strings that are prefixes of other strings in the array?

For example, if I start with this array:

$array = array('123', '234', '1234', '2345', '123456', '345', '1', 
               '12', 'six', 'one/two/three','six/seven','one/two');

I am trying to end up with this array:

$new_array = array('123456', '2345', '345', 'six/seven', 'one/two/three');

Because '12345' starts with '1234' which starts with '123' , etc.

I think I need to loop strings from the array and if the string length is bigger and it begins with the previous string, then replace the old string with the new string.

I would like to use this code

foreach ($array as $string) { 
    // compare with previous strings
    $new_array[] = $string; // replace prefixes of $string
}

but I do not know how to do the comparison. How can I accomplish this?

It looks like what you are wanting to do is group the array into sets of strings that extend the other strings in the group, and select the longest string from each group. The groups from the array

$old_array = array('123','234','1234','2345','123456','345','1','12');

would be

1, 12, 123, 1234, 123456
234, 2345
345

Here is one way to do this:

foreach ($old_array as $old) {

    // set a flag to indicate whether the value has already been added
    $matched = false;

    // loop over the new values by reference
    foreach ($new_array as &$new) {

        if ($new == $old) {  // this should prevent duplicate values from being added
            $matched = true; 

        } elseif ((strlen($old) > strlen($new)) && strpos($old, $new) === 0) {
            // if the old string starts with the new string, replace the value
            $new = $old;
            $matched = true;

        } elseif ((strlen($new) > strlen($old)) && strpos($new, $old) === 0) {
            // if the new string starts with the old string don't replace it and don't add it
            $matched = true;
        }
    }
    unset($new); // unset the reference

    if (!$matched) {
        // if no matching strings were found, add the string
        $new_array[] = $old;
    }
}

After looking at this again, it could be much less complicated if the input array was sorted first using SORT_STRING .

sort($old_array, SORT_STRING);
$old_array[] = null;  // append a null to force comparison of the last item
foreach ($old_array as $value) {
    if (isset($current) && !(strpos($value, $current) === 0)) {
        $new_array[] = $current;
    }
    $current = $value;
}

Based on your post I gather that you want to go through each element, from highest to lowest, and see if the current entry is contained in the most recent one where this has occured.

Try the below code, at the very least it outputs what you want.

$array = array('123','234','1234','2345','123456','345','1','12');

//First sort the array to get all of the bigger ones at the start
rsort($array);

//Then put the largest one in to the array, as you clearly want to start with something
$newArray[] = $array[0];

//Then loop through each value
foreach($array as $key => $value){

    //If the key is 0, then skip it, to avoid duplication
    if($key == 0){
        continue;
    }

    //Get the last entry of $newArray
    $lastEntry = end($newArray);

    //See if the current string is contained in the most recently saved one
    if(strpos($lastEntry, $value) !== false){

        //If so, add it to the new array
        $newArray[] = $value;
    }
}

//Just use the new Array instead of replacing the old one
var_dump($newArray);

//Uncomment this if you want to replace it
//$array = $newArray;

I have commented every part of it so you can see what each step does, if you have any more questions feel free to ask in a comment.

I think this is what you want. rsort($new_array);

sorting the number from highest to lowest.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM