usort function in a class

后端 未结 6 1204
孤城傲影
孤城傲影 2020-12-24 06:13

I have a function which sorts data in a multidimensional array, as shown below:

 \"James\");  
         


        
相关标签:
6条回答
  • I know this is an old thread, but I ran into another instance today that might benefit from another approach. I had a case where I wanted to use a specific key so I could abstract the actual support function. This led to finding a version using a wrapper function to return an anonymous function utilizing the 'use' command word to supply the name of the key used to sort in my class. (in my case, it's a key in a property on a [nested] class that is assigned to one of the class properties where I'm doing the sorting - i.e. I'm sorting instances based on a property in a 'dimensions' instance assigned to a property of 'items' and want to be able to sort them by width, height, length or weight for example). Then to get your function for the callback, you simply call this wrapper function with the key name you want to use to sort the result:

    /**
     * list of items
     *
     * @var Item[]
     */
    public $items;
    
    /**
     * @param string $key
     * @return \Closure
     */
    private static function keySort($key) {
        return function ($ia, $ib) use ($key) {
            if($ia->dimensions->$key == $ib->dimensions->$key) return 0;
            return ($ia->dimensions->$key < $ib->dimensions->$key) ? -1 : 1;
        };
    }
    
    /**
     * return the list of items in the items array sorted by the value
     *   of the property specified by $key
     *
     * @param string $key
     * @return Item[]
     * @throws \Exception
     */
    public function sortItemsByKey($key)
    {
        if(in_array($key, array( 'width', 'length', 'height', 'weight', ))) {
            return usort($this->items, static::keySort($key));
        } else
            throw new \Exception(__METHOD__ . ' invalid sort key!');
    }
    

    This allows me to call it local using either static:: or self:: (conceivably, I could even wrap it as a non-static function in this case since the only thing I'm worried about is getting the call but function returned) Another benefit I soon discovered is my dimensions object also has some 'calculated' fields such as girth, volume and dimensional weight. But one problem is that dimensional weight varies depending on if you are shipping an item domestically or internationally so I need to tell my 'calculateDimensionalWeight' function if it should use the value for international shipping or not. Well, using this method, I can do that by just passing an additional parameter to the wrapper function and adding the additional parameter to the use variables. Since I also need to make sure these values have been calculated prior to doing any comparisons, I can trigger that in my function based on the key:

    /**
     * @param string $key
     * @param bool $intl // only used for dimensional weight
     * @return \Closure
     */
    private static function keySort($key,$intl=false) {
        return function ($ia, $ib) use ($key,$intl) {
            switch($key) {
                case 'girth':
                    $ia->dimensions->calculateGirth();
                    $ib->dimensions->calculateGirth();
                    break;
                case 'dimweight':
                    $ia->dimensions->calculateDimensionalWeight($intl);
                    $ib->dimensions->calculateDimensionalWeight($intl);
                    break;
                case 'volume':
                    $ia->dimensions->calculateVolume();
                    $ib->dimensions->calculateVolume();
                    break;
            }
            if($ia->dimensions->$key == $ib->dimensions->$key) return 0;
            return ($ia->dimensions->$key < $ib->dimensions->$key) ? -1 : 1;
        };
    }
    
    /**
     * return the list of items in the items array sorted by the value
     *
     * @param string $key
     * @param bool $intl  (only used for dimensional weight sorts on international shipments)
     * @return Item[]
     * @throws \Exception
     */
    public function sortItemsByKey($key,$intl=false)
    {
        if(in_array($key, array('value','collect', 'width', 'length', 'height', 'weight', 'girth', 'dimweight', 'volume'))) {
            return usort($this->items, static::keySort($key,$intl));
        } else
            throw new \Exception(__METHOD__ . ' invalid sort key!');
    }
    

    NOTE: calculating values this way creates overhead as all but the first and last items in any list will technically be calculated twice which is redundant, but in this instance my lists are not long and in some cases, I need to compare two items when doing bin-sorting, so it's still preferable. For large datasets, it would probably be wiser to pre-calculate values external to the sort method.

    0 讨论(0)
  • 2020-12-24 06:35
    // If order_new is a NORMAL function 
    usort($data, [$this, 'order_new']);      // self ref object, function name  
    
    // If order_new is a STATIC function 
    usort($data, [__CLASS__, 'order_new']);  // string, function name 
    
    0 讨论(0)
  • 2020-12-24 06:37

    Change to usort($data, array($this, "order_new"));

    0 讨论(0)
  • 2020-12-24 06:38
     usort($data, array($this,"order_new"));
    

    is what you want when referring to a function in your class instance. See callable

    A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1.

    0 讨论(0)
  • 2020-12-24 06:46

    One thing to consider is that if the variable is passed to your method by reference, usort() appears to execute in the context of the referenced variable and not your current method. Therefore, you need to provide the full namespace in your class reference like so:

    usort($data, ['My\NameSpace\MyClass', 'order_new']); 
    
    0 讨论(0)
  • 2020-12-24 06:50

    order_new is a class method not a global function. As the PHP-Manual suggest you can use in this case

    usort($data, array($this, "order_new")); 
    

    or declare order_new static and use

    usort($data, array("myClass", "order_new")); 
    
    0 讨论(0)
提交回复
热议问题