How to re-order pages en-masse

First, the approach for setting up a sorting algorithm depends on where/how those street name and address numbers are stored. Single line in a meta_key, two separate meta_key entries, dumped into content for some reason, etc. etc. etc.

OP is dealing with addresses stored as post_title values. So below assumes string like:

1234 Main Street

The rest of it, matching and updating the page menu_order key is fairly straightforward.

Perhaps a process like this:

  • from init hook:

    [order_pages_by_values()]

  • get an array of page objects:

    [$pages = get_pages_wrapper();]

  • for each page object, pass the ID to a function that gets number/street values:

    1) [$addresses = extract_and_conflate_address( $pages );]

    2) [$number = get_address_number( $page->ID );]

    3) [$street = get_address_street( $page->ID );]

    4) [
    $split = explode( ' ', $address, 2 );
    if ( $value === 'number' ) {
    $return = $split[0];
    }
    elseif ( $value === 'street' ) {
    $return = $split[1];
    }
    ]

  • add number and street values to array as key => value, i.e. numeric => street:

    [$address_k_v[$number] = $street;]

  • sort the values and then keys of that array
  • create a multi-dimensional array of street => array ( numeric, )

    1) [$flatten_array = sort_values_and_keys_and_flatten( $addresses )]

    2) [

    foreach( $array as $n => $s ) {
    
    
        if ( array_key_exists( $s, $multi_array ) ) {
            $multi_array[$s][] = $n;
        }
        else {
             $multi_array[$s] = array( $n );
         }
      }
    

    ]

  • sort the street keys of outer array, then for each street, sort the inner numeric values array

    1) [ksort($multi_array);]

    2) [foreach ($multi_array as $street => $numbers_array ) {
    asort($numbers_array);
    ]

  • for each (now sorted) number => street entry, make that a string of number-street, and add it to a new array

  • for each (now sorted) street => array ( numeric ) (the inner array), add a string of number-street to a new array:

    [
    foreach( $numbers_array as $na ) {
    $flatten_array[] = $na .'-'. $street;
    ]

  • for each page object, get the number and the street again, this time using them to create a string of numberic-street:

    $number = get_address_number( $page->ID );
    $street = get_address_street( $page->ID ); 
    
    $match_string = $number . '-' . $street;`
    
  • search the array of sorted numberic-street strings for this numberic-street string, returning the index number to set $menu_order:

    [$menu_order = array_search( $match_string, $flatten_array );]

  • create args array for post with ID => page->ID and menu_order => index number:

    $update_post_args = array( 'ID'         => $page->ID,
                               'menu_order' => $menu_order
                            );
    
  • update post with those args:

    [wp_update_post( $update_post_args )]


It’s impossible to guess a solution without where those address fields are stored, but I’ve included a possible approach using explode on post_title in case that’s part of your current nightmare. 😉

The below is just an example of a possible process to start with of course, test it before giving it a full go. I’d probably wrap it all in a class of a plugin.

add_action( 'init', 'order_pages_by_values' );


function get_pages_wrapper() {
    $args = array( 'post_type'   => 'page',
                   'post_status' => 'publish'
                 );
    $pages = get_pages( $args );

    return $pages;
}


function extract_and_conflate_address( $pages ) {
    foreach ( $pages as $page ) {
        $number = get_address_number( $page->ID ); //depends on where value is stored
        $street = get_address_street( $page->ID ); //depends on where value is store

        $address_k_v[$number] = $street;
   }
   return $address_k_v;
}
//old version, several issues with this.
 // First, it is more of a re-sort, ignoring previously sorted items.
 /// Second, it cannot preserve instances where same post box address (1234) for different street would overwrite previous entry.
 /* function sort_values_and_keys( &$array, $valrev = false, $keyrev = false ) {
    //adopted from http://php.net/manual/en/function.asort.php#80798
    if ( $valrev ) { 

        arsort( $array );

    } else { 

        asort( $array );

    }

    $vals   = array_count_values( $array );
    $i      = 0;

    foreach ( $vals AS $val => $num ) {

        $first = array_splice( $array, 0, $i );

        $tmp   = array_splice( $array, 0, $num );

        if ( $keyrev ) { 

            krsort( $tmp ); 

        } else { 

            ksort( $tmp ); 
        }

        $array  = array_merge( $first, $tmp, $array );

        unset( $tmp );

        $i      = $num;
    }
} */

//Here we are creating a multidimensional array with the outer being Street
// and inner being an array of corresponding numerical post addresses.

function sort_values_and_keys_and_flatten( $array ) {
    //need array declared already for conditional inside foreach   
    $multi_array = array(); 

    foreach( $array as $n => $s ) {

       //makes sure Street doesn't exist yet. If it does, append, if not add.
        if ( array_key_exists( $s, $multi_array ) ) {
            $multi_array[$s][] = $n;
        }
        else {
             $multi_array[$s] = array( $n );
         }
    }

    //sort the street names
    ksort($multi_array);

    foreach ($multi_array as $street => $numbers_array ) {

        //sort the numerical addresses
        asort($numbers_array);

        //build $flatten_array
        foreach( $numbers_array as $na ) {

            $flatten_array[] = $na .'-'. $street;
        }
    }

    return $flatten_array;
 }



function order_pages_by_values() {

    $pages     = get_pages_wrapper();

    $addresses = extract_and_conflate_address( $pages );

   /**
     Replacing these lines with new sort function and setting $flatten to its return
    sort_values_and_keys( $addresses );

    foreach ( $addresses as $number => $street ) {

        $flatten_array[] = $number . '-' . $street;
    }
  */

    $flatten_array = sort_values_and_keys_and_flatten( $addresses );         

    foreach ( $pages as $page ) {

        $number = get_address_number( $page->ID ); //depends on where value is stored
        $street = get_address_street( $page->ID ); //depends on where value is stored

        $match_string = $number . '-' . $street;

        $menu_order = array_search( $match_string, $flatten_array );

        $update_post_args = array( 'ID'         => $page->ID,
                                   'menu_order' => $menu_order
                                );

        wp_update_post( $update_post_args );
    }

}

function get_address_number( $id ) {
    //assuming post_meta key of 'address_number'
    //$number = get_post_meta( $id, 'address_number', true ); 

    //assuming all addresses have format 1234 Main Street and saved as post title
    $number = extract_address( get_the_title( $id ), 'number' );
    return $number;
}
function get_address_street( $id ) {
    //assumes post_meta key of 'address_street'
    //$street = get_post_meta( $id, 'address_street', true ); 

    //assuming all addresses have format 1234 Main Street and saved as post title
    $street = extract_address( get_the_title( $id ), 'street' );
    return $street;
}
function extract_address( $address, $value ) {

    $split = explode( ' ', $address, 2 );
    if ( $value === 'number' ) {
        $return = $split[0];
    }
    elseif ( $value === 'street' ) {
        $return = $split[1];
    }

    return $return;
}

Update

I updated the code block above, but below is a quick test sample of the sorting function. I can’t say how economical it is, but it is working on my end.
Since it is returning the value needed for $flatten_array in the previous version, note above that I have removed those lines from order_pages_by_value()

Here is the testable code sample for the sort:

//array as would be returned by extract_and_conflate_addresses()
$the_array = array( 
            '1234'      => 'Main Street',
            '100'       => 'Avenue Road',
            '105'       => 'Avenue Road',
            '106'       => 'Avenue Road',
            '106a'      => 'Avenue Road',
            '107'       => 'Avenue Road',
            '103'       => 'Front Street',
            '42'        => '5 Lane',
            '42000'     => 'B Street',
    );


function sort_values_and_keys_and_flatten( $array ) {

    //need array declared already for conditional inside foreach   
    $multi_array = array(); 

    foreach( $array as $n => $s ) {

        //makes sure Street doesn't exist yet. If it does, append, if not add.
        if ( array_key_exists( $s, $multi_array ) ) {
            $multi_array[$s][] = $n;

        }
        else {
             $multi_array[$s] = array( $n );
         }

    }

    //sort the street names
    ksort($multi_array);

    foreach ($multi_array as $street => $numbers_array ) {

        //sort the numerical addresses
        asort($numbers_array);

        //build $flatten_array
        foreach( $numbers_array as $na ) {

            $flatten_array[] = $na .'-'. $street;
        }

    }

    return $flatten_array;

}

$test = sort_values_and_keys_and_flatten( $the_array );
print_r($test);

That should yield:

Array
(
    [0] => 42-5 Lane
    [1] => 100-Avenue Road
    [2] => 105-Avenue Road
    [3] => 106-Avenue Road
    [4] => 106a-Avenue Road
    [5] => 107-Avenue Road
    [6] => 42000-B Street
    [7] => 103-Front Street
    [8] => 1234-Main Street
)