كيفية إنشاء بنية البيانات مع التكرارات الرئيسية في PHP بدلاً من التجزئة الافتراضية؟
سؤال
أرغب في إنشاء فئة 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