php 类中的 usort 函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11312986/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 00:15:02  来源:igfitidea点击:

usort function in a class

php

提问by Marinus

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

我有一个对多维数组中的数据进行排序的函数,如下所示:

<?php  
$data = array();  
$data[] = array("name" => "James");  
$data[] = array("name" => "andrew");  
$data[] = array("name" => "Fred");  

function cmp($a, $b)  
{  
    return strcasecmp($a["name"], $b["name"]);  
}  

usort($data, "cmp");  

var_dump($data);  
?>  

When i run this, it works as expected, returning the data ordered by name, ascending. However, I need to use this in a class.

当我运行它时,它按预期工作,返回按名称排序的数据,升序。但是,我需要在课堂上使用它。

<?php
class myClass  
{  
    function getData()  
    {  
        // gets all data
        $this -> changeOrder($data);
    }  

    function changeOrder(&$data)  
    {  
         usort($data, "order_new");
    }

    function order_new($a, $b)  
    {  
        return strcasecmp($a["name"], $b["name"]);  
    }
}
?>

When I use this, i get the following warning: Warning: usort() expects parameter 2 to be a valid callback, function 'order_new' not found or invalid function name.

当我使用它时,我收到以下警告:警告:usort() 期望参数 2 是一个有效的回调,找不到函数“order_new”或无效的函数名称。

When i put the order_new function in the changeOrder function it works fine, but I have problems with Fatal error: Cannot redeclare order_new(), so i cannot use that. Any suggestions?

当我将 order_new 函数放在 changeOrder 函数中时,它工作正常,但我遇到了致命错误的问题:无法重新声明 order_new(),所以我不能使用它。有什么建议?

回答by worenga

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

order_new 是一个类方法而不是一个全局函数。正如PHP-Manual建议您可以在这种情况下使用

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

or declare order_new static and use

或声明 order_new 静态并使用

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

回答by xdazz

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

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

回答by Harald Brinkhof

 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 处的对象和索引 1 处的方法名称。

回答by beltashazzar

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() 似乎在引用变量的上下文中执行,而不是在您当前的方法中执行。因此,您需要在类引用中提供完整的命名空间,如下所示:

usort($data, ['My\NameSpace\MyClass', 'order_new']); 

回答by Scott

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:

我知道这是一个旧线程,但我今天遇到了另一个可能受益于另一种方法的实例。我有一个案例,我想使用一个特定的键,这样我就可以抽象出实际的支持功能。这导致找到使用包装函数返回匿名函数的版本,该函数使用“use”命令字提供用于在我的类中排序的键的名称。(在我的情况下,它是 [嵌套] 类上的属性中的一个键,该属性分配给我正在执行排序的类属性之一 - 即我正在根据“维度”实例中的属性对实例进行排序分配给“项目”的属性,并希望能够按宽度、高度、长度或重量对它们进行排序)。然后获取回调函数,

/**
 * 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:

这允许我使用 static:: 或 self:: 调用它本地(可以想象,在这种情况下,我什至可以将它包装为非静态函数,因为我唯一担心的是获取调用但函数返回)我很快发现的另一个好处是我的尺寸对象还有一些“计算”字段,例如周长、体积和尺寸重量。但一个问题是,尺寸重量取决于您是在国内还是在国际上运输物品,因此我需要告诉我的 'calculateDimensionalWeight' 函数是否应该使用国际运输的值。嗯,使用这种方法,我可以通过向包装函数传递一个附加参数并将附加参数添加到 use 变量来做到这一点。

/**
 * @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.

注意:以这种方式计算值会产生开销,因为任何列表中的第一个和最后一个项目在技术上都会计算两次,这是多余的,但在这种情况下,我的列表不长,在某些情况下,我需要在执行时比较两个项目bin-sorting,所以它仍然是可取的。对于大型数据集,预先计算 sort 方法外部的值可能更明智。

回答by Jpsy

// 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