كيفية إنشاء بنية البيانات مع التكرارات الرئيسية في PHP بدلاً من التجزئة الافتراضية؟

StackOverflow https://stackoverflow.com/questions/1796937

  •  22-09-2019
  •  | 
  •  

سؤال

أرغب في إنشاء فئة Wrapper ، والتي ستمكن مفاتيح التكرارات في حين أن التجزئة الافتراضية لا تسمح بذلك. يجب على الفصل استخدام آلية التحميل الزائد للأعضاء التي تم تقديمها في PHP5 ، لذلك من شأنه أن يقلد جميع التجزئة القياسية للسلوك. على سبيل المثال ، أريد أن أحصل على SMTH

$var => obj( :values_arr -> array(
      obj(:key -> 'mykey', :value -> 'val1'), 
      obj(:key -> 'mykey', :value -> 'val2')
    )
)

إذا كنت أرغب في الحصول على $ var ['mykey'] ، فيجب أن ترجع صفيف ('val1' ، 'val2') ، ولكن إذا أردت تمديد OBJ مع زوج جديد 'mykey' => '' value '، سأتصل

$val['mykey'][] = 'value'

الفكرة الرئيسية هي أنه تم الحفاظ على سلوك التجزئة وبعد محاولة تعيين قيمة لاستخدام المفتاح الحالي ، لن يتم الكتابة فوقه ، ولكن تم إلحاقه بالقائمة.

كيف يمكنك تقليد هياكل البيانات الأخرى في PHP5 (قبل 5.3)؟ هل هناك أي حلول أو أمثلة معروفة تريد مشاركتها؟

هل كانت مفيدة؟

المحلول

مثله

class MultiMap
{
    protected $map = array();

    function __set($key, $val) {
        if(!isset($this->map[$key]))  
           return $this->map[$key] = $val;
        if(!is_array($this->map[$key]))
           $this->map[$key] = array($this->map[$key]);
        $this->map[$key][] = $val;
    }
    function __get($key) {
       return $this->map[$key];
    }
}

$m = new MultiMap;
$m->foo = 1;
$m->foo = 2;
$m->bar = 'zzz';
print_r($m->foo);
print_r($m->bar);

لكن الفكرة كلها تبدو غريبة بعض الشيء بالنسبة لي. هل يمكنك شرح لماذا تحتاج هذا؟

ليس من الواضح بالنسبة لي لماذا تحتاج إلى مشغليين كمفاتيح في AST ربما تكون بنية مثل هذا أكثر ملاءمة

   ('op' => 'AND', 'args' => [
        (op => AND, args => [
            (op  => atom, value => word1),
            (op  => atom, value => word2),
        ]),
        (op => AND, args => [
            (op  => atom, value => word3),
            (op  => atom, value => word4),
        ])
    ])

نصائح أخرى

يمكنك تحقيق بناء جملة المصفوفة

$val['mykey'] = 'value';

مع ال ArrayAccess واجهه المستخدم

class MultiHash implements ArrayAccess, IteratorAggregate
{
    protected $data;

    public function offsetGet($offset)
    {
        return $this->data[$offset];
    }
    public function offsetSet($offset, $value)
    {
        if ($offset === null) { // $a[] = ...
            $this->data[] = array($value);
        } else {
            $this->data[$offset][] = $value;
        }
    }
    public function offsetExists($offset)
    {
        return isset($this->data[$offset]);
    }
    public function offsetUnset($offset)
    {
        unset($this->data[$offset]);
    }

    public function getIterator()
    {
        $it = new AppendIterator();
        foreach ($this->data as $key => $values) {
            $it->append(new ConstantKeyArrayIterator($values, 0, $key));
        }
        return $it;
    }
}

class ConstantKeyArrayIterator extends ArrayIterator
{
    protected $key;

    public function __construct($array = array(), $flags = 0, $key = 0)
    {
        parent::__construct($array,$flags);
        $this->key = $key;
    }
    public function key()
    {
        return parent::key() === null ? null : $this->key;
    }
}

أنا أيضا تنفيذ IteratorAggregate للسماح للتكرار على جميع العناصر المفردة.

رمز الاختبار

$test = new MultiHash();
$test[] = 'foo';
$test[] = 'bar';
$test['mykey'] = 'val1';
$test['mykey'] = 'val2';
$test['mykey2'] = 'val3';

echo "mykey: ";
var_dump($test['mykey']);

echo "mykey2: ";
var_dump($test['mykey2']);

echo "iterate:\n";
foreach ($test as $key => $value) {
    echo "$key : $value \n";
}

اختبار الإخراج

mykey: array(2) {
  [0]=>
  string(4) "val1"
  [1]=>
  string(4) "val2"
}
mykey2: array(1) {
  [0]=>
  string(4) "val3"
}
iterate:
0 : foo 
1 : bar 
mykey : val1 
mykey : val2 
mykey2 : val3 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top