мульти-индексевый масив

WMix

герр M:)ller
Партнер клуба
допустим существует класс
PHP:
class Model{
    protected $data;
    protected $map;

    public function set( $data ){
        $this->data = $data;
    }

    public function prepare( $v ){
        foreach($this->data as $idx => $val){
            foreach( $v as $operation => $keys ){
                foreach( $keys as $key ){
                    switch($operation){
                        case 'unique' :
                            $this->map[ $key ][ $val[ $key ] ] = &$this->data[$idx];
                            break;
                        case 'group' :
                            $this->map[ $key ][ $val[ $key ] ][ $idx ] = &$this->data[$idx];
                            break;
                    }
                }
            }
        }
    }

    public function get( $where ){
        if( is_array($where) ) return $this->map[ key($where) ][ current($where) ];
        else return array_keys( $this->map[ $where ]);
    }
}
допустим мы создали такой обьектик
PHP:
$s = new Model;
$s->set( array(
    array('id' => 'a', 'type' => 1, 'value' => 'mama' ),
    array('id' => 'b', 'type' => 2, 'value' => 'mama' ),
    array('id' => 'c', 'type' => 1, 'value' => 'papa' )
) );
подкрутили
PHP:
$s->prepare( array(
    'unique' => array('id','value'),
    'group' => array('type')
));
с этого момента можно искать по любому ключу

это удобно во вьюшке, то такой, то такой масcив выпрашивать!
PHP:
print_r($s->get( array('id' => 'a') ));
print_r($s->get( array('value' => 'mama') ));
print_r($s->get( 'id' ));
print_r($s->get( 'value' ));
foreach($s->get( 'type' ) as $type){
    echo $type ."\n";
    print_r( $s->get( array('type'=>$type ) ));
}
своего рода индекс таблицы :)

существует ли подобная структура данных или алгоритм и как это завется?
 
Последнее редактирование:

artoodetoo

великий и ужасный
WMix, встречал подобный класс (не в PHP), но это было самостоятельное изобретение, а не адаптация паттерна.
я считаю Вы имеете полное моральное право придумать название. даже присвоить своё имя :)
 

stopkran

Дилетант
Идея в принципе полезная, только вот я как-то ожидал, что это:
PHP:
print_r($s->get( array('value' => 'mama') ));
- вернёт все элементы с value 'mama', а оно возвращает только один элемент:

Array
(
[id] => b
[type] => 2
[value] => mama
)
 

WMix

герр M:)ller
Партнер клуба
artoodetoo
не имени ради, а подглядеть для

stopkran
если группировать по value, то будут оба значения. (в моем примере просто приведены различные способы и их разница)
PHP:
$s->prepare( array(
    'group' => array('value')
));

print_r($s->get( array('value' => 'mama') ));
Код:
Array
(
    [0] => Array
        (
            [id] => a
            [type] => 1
            [value] => mama
        )

    [1] => Array
        (
            [id] => b
            [type] => 2
            [value] => mama
        )

)
 
Последнее редактирование:

AmdY

Пью пиво
Команда форума
hell0w0rd
нет, identity map это подвид singleton, он гарантирует что ты работаешь с одним и тем же объектом
PHP:
$a = User::find(1);
$b = User::find(1);
$a->foo = 'bar';
$b->foo // bar
 

hell0w0rd

Продвинутый новичок
AmdY
Ясно, но нам же нужно по разным ключам получать одно и то же значение? В доктрине как раз и хранятся по первичным ключам все загруженные сущности, тут я так понял нужно то же самое
 

WMix

герр M:)ller
Партнер клуба
hell0w0rd
согласен, мой пример чемто напоминает кастрированый кусок IdentityMap, но я всеже несколько о другом, данные уже получены (в смысле модель уже сделала свое дело), вопрос только в представлении полученного результата. те. в зависимости от view ожидаем иной подход к полученой моделе. в моем примере можно было представить в виде таблицы (uniq) или каталога (group).

хочу иметь некий трансформатор данных, чтоб основные структуры не описывать всякими viewHelper: хочу меню? - выбрал все ключи!
 
Последнее редактирование:

hell0w0rd

Продвинутый новичок
WMix
PHP:
class MultiIndexArray
{
    private $data = array();

    public function __construct(array $data)
    {
        $this->data = $data;
    }

    public function getWith($index, $value, $limit = null)
    {
        foreach ($this->data as $data) {
            if ($limit !== null && --$limit < 0) {
                yield;
            }
            if ((isset($data[$index]) || ($value === null && array_key_exists($index, $data))) &&
                $data[$index] === $value) {
                yield $data;
            }
        }
    }
}

$arr = new MultiIndexArray(array(
    array('id' => 'a', 'type' => 1, 'value' => 'mama' ),
    array('id' => 'b', 'type' => 2, 'value' => 'mama' ),
    array('id' => 'c', 'type' => 1, 'value' => 'papa' )
));
foreach($arr->getWith('value', 'mama') as $data) {
    var_dump($data);
}
Не думаю что у тебя такие большие объемы данных, что нужно прям индекс строить...
 

WMix

герр M:)ller
Партнер клуба
да, вот так и я пишу, и один и тотже масив по 5-20 раз на класс перекручиваю
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
да-да, WMix, первая мысль в моей голове - надо sql писать под логику, а не выбирать все подряд на все случаи жизни и в php выполнять работу БД
 

WMix

герр M:)ller
Партнер клуба
AmdY
прикольно, поразбираюсь, конечно так много лишнего, но идея очень похожа!

keltanas
да чтото подобное хочу, но не базу а простые трансформации/срезы

grigori
представь простой счет.
там дата, номер блаблабла и позиции.
создали модельку вытянули все из базы. вроде все готово и ничего лишнего.

вдруг появляется желание показывать позиции счета не только в ряд/столбик/таблицей но и по категориям продуктов.
PHP:
$s->prepare(array('group'=>'category')
foreach($s->get('category') as $item){...}
далее желание по странам производителям опять
PHP:
$s->prepare(array('group'=>'country')
foreach($s->get('country') as $item){...}
можно все эти методы в моделе имплементировать, можно кучу viewHelperов написать, а можно просто создать trait типо как пример класса Model и использовать
 
Последнее редактирование:

grigori

( ͡° ͜ʖ ͡°)
Команда форума
>вдруг появляется желание показывать позиции счета не только в ряд/столбик/таблицей но и по категориям продуктов.
ActiveRecord не пробовал?

да, можно написать и так, как ты, уволиться, продуктов станет больше, потом еще больше, сайт начнет падать все чаще, yandex будет показывать проблемы с доступностью, придет кто-нибудь вроде меня и спросит: что за дебил такое сделал?
почти каждый день спрашиваем
 

AmdY

Пью пиво
Команда форума
grigori
скорее наоборот, это попытка сделать стандартный DSL для работы с коллекциями, вместо явных итераций в foreach, array_mat, array_filter и т.д. вполне здравая идея, только в итоге превращающая ещё в одного монстра типа doctrine 2.
это позволит обойтись без сложных sql запросов и т.д.
 

WMix

герр M:)ller
Партнер клуба
разве дело в activ-record, разговор о простой визуализации чего угодно. метод set примет Iterator, next() которого вернет bean, хочешь ActiveRecord. просто определенные циклы хочу описать правилами, довольно логично на мой взгляд, но понимаю что это велосипед и ищу слово которое подскажет как делать правильно.

я вообще если чесно не понимаю почему в скриптовом языке не создали структуру где возможны такие операции как
PHP:
foreach( $a[*]['id'] as key=>$val){}
скоро с++ будет более богат всякими фишечками
 
Последнее редактирование:

WMix

герр M:)ller
Партнер клуба
hell0w0rd
нет проблем, задолбало писать одно и тоже, концентрироваться на мелочах, да и не безбагово это. Наверно крик души)
 
Последнее редактирование:

hell0w0rd

Продвинутый новичок
PHP:
foreach( $a[]['id'] as key=>$val){}
скоро с++ будет более богат всякими фишечками
А можно пример что выберет эта коснтрукция? Разве такое с помощью итераторов/генераторов сделать нельзя?
Ну а плюсы заведомо круче по кастомизации синтаксиса) Там как минимум есть #define, libcello (хоть и си) тому пример)
И все что бы не было за этой конструкцией - для view придумали шаблонизаторы, хоть обпридумывайся конструкций
 
Сверху