Sorting get_terms, ACF is automatically removing duplicates

PHP does not allow duplicate keys, the previous key/value pair is simply replaced with the current key/value pair. Anyways, lets look at your code and how we will solve it

You have a few issues here

  • You should not be using extract(), ever. It was removed from core a few years ago for very specific reasons. Please read @toscho’s answer regarding extract()

  • Always sanitize and validate any user submitted data, even if that data is coming from you. User input data may contain malicious code which a hacker can use to get access to your site

  • $html is an undefined variable in your code, which is a bug. If you have debug turned on, you would get an explicit notice about that. Always define a variable before trying to use it, and always have debug set to true on your local test install

  • You are using get_terms() wrongly. The second parameter takes an array of parameters which does not include the taxonomy. The taxonomy is passed as first parameter

  • You are using ACF and ACF functions which will crash your site should ACF be uninstalled. Always do a check to make sure that external functions exists before suing it to avoid WSOD. Just a tip here, as from WordPress 4.4, you can now make use of the term metadata table to store additional info related to a term and then use that data to sort terms by. ACF is almost always a pain in the butt to remove when you no longer need the plugin

  • krsort is definitely the wrong sorting function to use in your current code. usort() should have being the correct sorting function to use. In our new code, krsort() would work perfectly

Lets look at better workaround. I accept that you need to display terms sorted by ACF field. You can try the following: (NOTE: The code below is untested and might be buggy. Also, I don’t know the ACF plugin, make sure about my usage of get_field())

add_shortcode( 'ranker', 'ranker_shortcode' );
function ranker_shortcode( $atts ) 
{
    // Define our defualt attributes
    $attributes = shortcode_atts( 
        [
            'taxonomy' => '',
        ], $atts 
    );

    // Set our $html variable as empty string
    $html="";

    // Sanitize and validate our taxonomy to avoid bugs later on. Return $html should anything fail
    $taxonomy = filter_var( $attributes['taxonomy'], FILTER_SANITIZE_STRING );
    if ( !$taxonomy )
        return $html;

    if ( !taxonomy_exists( $taxonomy ) )
        return $html;

    // We made it to hear, check if the ACF plugin is activated and that get_field() exists
    if ( !function_exists( 'get_field' ) )
        return $html;

    // Great, we made it to here, our checks checked out, lets continue
    $terms  = get_terms( $taxonomy );

    // Make sure we have terms, no need to check for WP_Error object because we know the taxonomy exists
    if( !$terms )
        return $html;

    // We have terms, lets loop through them and build our array
    $sorted = [];
    foreach ( $terms as $term ) {
        // Get our field value and make sure we have a field value, if not, just continue
        $field  = get_field( 'height', $term ); // Make sure we can pass the term object, don't know ACF

        if ( !$field )
            continue;

        // Our term have a field, lets build the array
        $sorted[$field][]  = $term->name;
    }

    // Lets sort the array DESC according to array key, which is our $field value
    krsort( $sorted, SORT_NUMERIC ); // Make sure here that your field is actually numeric to avoid bugs

    if ( !$sorted )
        return $html;

    // We are done, lets build our string and return it
    foreach( $sorted as $key=>$value ) {
        foreach ( $value as $v ) {
            $html .= $key . ', ' . $v . '<br>';
        }
    }
    return $html;
}