是否有可能在PHP中实现独特的价值?

时间:2018-07-15 21:08:29

标签: php

我正在创建一个数组类,希望一个值能够被高阶函数返回。这个想法是它的实例常量或方法返回值,这样我就可以跳过map中的值。

在其他语言中,创建数组或某个复合值(例如['skip'])将使其等于指针,这样我就可以使用运算符将​​其等于指针,并且它将不等于具有相同内容的其他数组,但是我的问题是['skip'] === ['skip']是正确的,因此即使使用===,两个值也相同。

这是我的代码用法示例,其中我具有与过去跳过相同的值:

namespace Test;
use Common\Domain\Collection;

$arr = new Collection();
$arr[] = 1;
$arr[] = 2;
$arr[] = 3;
$arr[] = 4;
echo count($arr); // prints 4
$arr2 = $arr->map(function ($v) { 
    return $v % 2 == 0 ? Collection::SKIP : ["skip"]; 
});
echo count($arr2); // prints 0, but should be 2

是否有办法获得独特的价值或以某种方式解决? 这是实现Collection的代码:

namespace Common\Domain;;

class Collection implements \Iterator, \Countable, \ArrayAccess
{
    const SKIP = ["skip"];
    private $arr = [];

    public function map(callable $fn, bool $keepKeys = false) :Collection
    {
        $arr = new static();
        $nOrder = 0;
        foreach($this->arr as $key => $value) {
            $result = call_user_func($fn, $value, $key, $nOrder, $this);
            if($result !== self::SKIP) {
                if($keepKeys) {
                    $arr[$key] = $result;
                } else {
                    $arr[] = $result;
                }
            }
        }
        return $arr;
    }

    // implementation of interfaces \Iterator, \Countable, \ArrayAccess

    public function current()
    {
        return current($this->arr);
    }

    public function next()
    {
        next($this->arr);
    }

    public function key()
    {
        return key($this->arr);
    }

    public function valid()
    {
        return isset($this->arr[$this->key()]);
    }

    public function rewind()
    {
        reset($this->arr);
    }

    public function count()
    {
        return count($this->arr);
    }

    public function offsetExists($offset)
    {
        return array_key_exists($offset, $this->arr);
    }

    public function offsetGet($offset)
    {
        return $this->arr[$offset];
    }

    public function offsetSet($offset, $value)
    {
        $this->arr[$offset] = $value;
    }

    public function offsetUnset($offset)
    {
        unset($this->arr[$offset]);
    }

}

2 个答案:

答案 0 :(得分:1)

我猜您正在寻找Java类型的枚举,PHP中不存在。我对您的问题的最佳猜测是使用一个对象而不是一个常量,您可以将其静态实例化以方便使用。然后,在map函数的循环中,使用instanceof而不是基本的相等运算符,根据定义的类检查值。

所以,这里:

class UniqueValue
{
    public static function get()
    {
        return new self();
    }
}

然后:

$arr2 = $arr->map(function ($v) { 
    return $v % 2 == 0 ? UniqueValue::get() : ["skip"]; 
});

在您的收藏夹中:

public function map(callable $fn, bool $keepKeys = false) :Collection
    {
        $arr = new static();
        $nOrder = 0;
        foreach($this->arr as $key => $value) {
            $result = call_user_func($fn, $value, $key, $nOrder, $this);
            if($result ! instanceof UniqueValue) {
                if($keepKeys) {
                    $arr[$key] = $result;
                } else {
                    $arr[] = $result;
                }
            }
        }
        return $arr;
    }

这是我能想到的最快的方法。如果您的数组包含“外部”数据,则我认为它不可能与您自己代码中的类检查相匹配。

答案 1 :(得分:0)

我将通过为此实现另一种方法来解决此问题。方法delete将一个函数映射到集合上,并删除该函数返回false的所有元素。

例如

class Collection
{
// ...
    public function delete($func)
    {
        $result = new static();
        foreach($this->arr as $item)
        {
            if($func($item) !== false) $result[] = $item;
        }
    }
}

// example

$arr = new Collection();
$arr[] = 1;
$arr[] = 2;
$arr[] = 3;
$arr[] = 4;
echo count($arr); // prints 4
$arr2 = $arr->delete(function ($v) { 
  return $v % 2 ? true : false;
});
var_dump($arr2); // prints [2, 4]