Извлечение нескольких значений массива с извлечением - программирование
Подтвердить что ты не робот

Извлечение нескольких значений массива с извлечением

array(
    [0]=>
        [index1]=>something
        [index2]=>something else
        [index3]=>something more
    [1]=>
        [index1]=>something
        [index2]=>something else
        [index3]=>something more
    [2]=>
        [index1]=>something
        [index2]=>something else
        [index3]=>something more
)

EDIT: Поэтому я хотел бы получить следующее:

array(
    [0]=>
        [index1]=>something
        [index2]=>something else
    [1]=>
        [index1]=>something
        [index2]=>something else
    [2]=>
        [index1]=>something
        [index2]=>something else
)

Как получить несколько индексов массива с помощью функции Set:: extract в cakephp?

Это возвращает одно значение:

Set::extract($array, '{n}.index1');

но я хотел бы получить несколько значений... скажем, index1 и index2.

Я пробовал заявления вроде следующего, безрезультатно.

Set::extract($array, '[{n}.index1, {n}.index2']);

ИЗМЕНИТЬ

    $__pages = Hash::merge(
                    Hash::extract($pages, 'pages.{n}.id'),
                    Hash::extract($pages, 'pages.{n}.title')
                    );
    pr($__pages);

Вывод:

Array
(
    [0] => 2
    [1] => 4
    [2] => 104
    [3] => Sample Page
    [4] => about us
    [5] => Services
)

Это не помогает мне, так как мне все еще нужна ассоциация:

Array(
   [2] => Sample Page
   [4] => About us
   [104] => Services
)

Я был бы даже доволен:

Array(
   Array(id => 2, title => Sample Page)
   Array(id => 4, title => About Us)
   Array(id => 104, title => Services)
)

ANSWER Ответ thecodeparadox работает на тестовый код, который я предоставил. Вот код реальной жизни, если кто-то споткнется здесь. В книге говорится, что "любой строковый литерал, заключенный в скобки, кроме {n} и {s}), интерпретируется как регулярное выражение". Эта линия казалась скрытой и не очень вопиющей. Поэтому, зная это, я просто использовал правила регулярных выражений, чтобы получить нужные мне данные. У меня есть массив, который вытащил сообщения wordpress из api, мне нужно было сузить результаты до id, title.

array(
   posts=>
      0=>
         id => 3
         slug => sample-page
         type => page
         title => Sample Page
         //...and so on 

      1=>
         id => 7
         slug => sample-page-2
         type => page
         title => Sample Page 2
         //...and so on 

Чтобы получить только идентификатор и заголовок, я добавил следующую строку.

pr(Set::classicExtract($pages, 'pages.{n}.{(id|title)}'));

это дало мне:

array(
   posts=>
      0=>
         id => 3
         title => Sample Page

      1=>
         id => 7
         title => Sample Page 2

ДОКУМЕНТАЦИЯ: Book

4b9b3361

Ответ 1

$arr = array(
            array(
                'index1'=>'something',
                'index2'=>'something else',
                'index3'=>'something more',
            ),
            array(
                'index1'=>'something',
                'index2'=>'something else',
                'index3'=>'something more',
            ),
            array(
                'index1'=>'something',
                'index2'=>'something else',
                'index3'=>'something more',
            )
        );

$output = Set::classicExtract($arr, '{n}.{index[1-2]}');

print_r($output);

// output


Array
(
    [0] => Array
        (
            [index1] => something
            [index2] => something else
        )

    [1] => Array
        (
            [index1] => something
            [index2] => something else
        )

    [2] => Array
        (
            [index1] => something
            [index2] => something else
        )

)

Ответ 2

Вы пробовали Set:: extract ($ array, '{n}. {s}');

EDIT: Если размер вашего массива точно такой же, как в ответе, вы можете попробовать array_keys (Set:: extract ($ array, '{n}. {s}'));

Ответ 3

Один из способов (если вы хотите сохранить только несколько результатов):

Hash::merge(
    Hash::extract($array, '{n}.index1'),
    Hash::extract($array, '{n}.index2')
);

Другой способ (если вы хотите удалить только несколько):

Hash::remove($array, '{n}.index3');

Ответ 4

Я не уверен, почему вы хотите придерживаться класса Set? Если это вам не подходит, зачем вы его используете, а не создаете свою собственную функцию? Вы говорите в одном из своих комментариев, что хотите избежать циклов foreach. Но методы класса Set полны foreach циклов themselve. Я могу пропустить пункт...

Personnaly Я бы сделал это просто с помощью функции, подобной этой:

function filter_fields($array_to_filter, $fields_to_keep)
{
    foreach($array_to_filter as $i => $sub_array)
    {
        foreach($sub_array as $field => $value)
        {
            if(!in_array($field, $fields_to_keep))
            {
                unset($array_to_filter[$i][$field]);
            }
        }
    }

    return $array_to_filter;
}

Вот пример того, что он вернет:

print_r($array_to_filter);
/*
Array
(
    [0] => Array
        (
            [index1] => abc
            [index2] => def
            [index3] => ghi
        )

    [1] => Array
        (
            [index1] => jkl
            [index2] => mno
            [index3] => poq
        )
)
*/

$filtered_array = filter_fields($array_to_filter, array('index1', 'index3'));

print_r($filtered_array);
/*
Array
(
    [0] => Array
        (
            [index1] => abc
            [index3] => ghi
        )

    [1] => Array
        (
            [index1] => jkl
            [index3] => poq
        )
)
*/

Ответ 5

Набор УДИВИТЕЛЬНО! Вы не можете сделать это напрямую с помощью Set:: extract, но вы можете построить ассоциативный массив из двух индексов массива с помощью Set:: comb:

Set::combine($myArray, '{n}.index1', '{n}.index2')

Рабочий пример выглядит следующим образом:

$myArray = array(
    array('index1'=>'something 1', 'index2'=>'something else 1', 'index3'=>'something more 1'),
    array('index1'=>'something 2', 'index2'=>'something else 2', 'index3'=>'something more 2'),
    array('index1'=>'something 3', 'index2'=>'something else 3', 'index3'=>'something more 3'),
);

debug(Set::combine($myArray, '{n}.index1', '{n}.index2'));

Это займет такой массив, как вы упомянули:

array(
[0]=>
    [index1]=>something 1
    [index2]=>something else 1
    [index3]=>something more 1
[1]=>
    [index1]=>something 2
    [index2]=>something else 2
    [index3]=>something more 2
[2]=>
    [index1]=>something 3
    [index2]=>something else 3
    [index3]=>something more 3

)

и превратите его в это:

Array (
    [something1] => something else 1
    [something2] => something else 2
    [something3] => something else 3
)

Ответ 6

[+10] Большие пальцы вверх для раскрытия метода classicExtract для меня в этом сообщении.

Пример массива:

$params = array(
  'key-1'=>array('subkey'=>array('x'), 'junk'), 
  'key-2'=>array('subkey'=>array('y'), 'otherkey'=>'more junk')
);

Проблема у меня:

Базовый ключ преобразуется в int.

 eg. array(0=>array('x'), 1=>array('y'))

Решение:

$array = Hash::filter(Set::classicExtract($params, '{[a-zA-Z0-9-_.]}.subkey'));

возвращает:

eg. array('key-1'=>array('x'), 'key-2'=>array('y'))

При необходимости измените регулярное выражение в ключе.

Просто написал эту функцию

Он даст возможность анализировать массив с помощью {a) вместо {s}

{a} для ассоциативного ключа для базы.

называется так: static:: extract ($ array, '{a}.subkey');

  public static function extract($array, $path, $filter=true){
    $path = str_replace("{a}", "{[a-zA-Z0-9-_.]}", $path);
    if(is_array($array)){
      $return = Set::classicExtract($array, $path);
      if($filter){
        if(is_array($return)){
          $return = Hash::filter($return);
        }
      }
      return $return;
    }
  }

[[ОБНОВЛЕНИЕ ДЛЯ ТОРТА 3]]

Если вы использовали эту функцию, я вижу, что cakephp просто удалил заданный класс. Вы можете заставить его снова работать, добавив к классу classExtract метод

use Cake\Utility\Hash;

public static function classicExtract($data, $path = null)
{
    if (empty($path)) {
        return $data;
    }
    if (is_object($data)) {
        if (!($data instanceof \ArrayAccess || $data instanceof \Traversable)) {
            $data = get_object_vars($data);
        }
    }
    if (empty($data)) {
        return null;
    }
    if (is_string($path) && strpos($path, '{') !== false) {
        $path = \Cake\Utility\String::tokenize($path, '.', '{', '}');
    } elseif (is_string($path)) {
        $path = explode('.', $path);
    }
    $tmp = array();

    if (empty($path)) {
        return null;
    }

    foreach($path as $i => $key) {
        if (is_numeric($key) && intval($key) > 0 || $key === '0') {
            if (isset($data[$key])) {
                $data = $data[$key];
            } else {
                return null;
            }
        } elseif ($key === '{n}') {
            foreach($data as $j => $val) {
                if (is_int($j)) {
                    $tmpPath = array_slice($path, $i + 1);
                    if (empty($tmpPath)) {
                        $tmp[] = $val;
                    } else {
                        $tmp[] = static::classicExtract($val, $tmpPath);
                    }
                }
            }
            return $tmp;
        } elseif ($key === '{s}') {
            foreach($data as $j => $val) {
                if (is_string($j)) {
                    $tmpPath = array_slice($path, $i + 1);
                    if (empty($tmpPath)) {
                        $tmp[] = $val;
                    } else {
                        $tmp[] = static::classicExtract($val, $tmpPath);
                    }
                }
            }
            return $tmp;
        } elseif (strpos($key, '{') !== false && strpos($key, '}') !== false) {
            $pattern = substr($key, 1, -1);

            foreach($data as $j => $val) {
                if (preg_match('/^'.$pattern.'/s', $j) !== 0) {
                    $tmpPath = array_slice($path, $i + 1);
                    if (empty($tmpPath)) {
                        $tmp[$j] = $val;
                    } else {
                        $tmp[$j] = static::classicExtract($val, $tmpPath);
                    }
                }
            }
            return $tmp;
        } else {
            if (isset($data[$key])) {
                $data = $data[$key];
            } else {
                return null;
            }
        }
    }
    return $data;
}

//CAKEPHP METHODS
public static function extract($array, $path, $filter = true)
{
    $return = [];
    if (is_array($array)) {
        if (stristr($path, '{a}')) {
            $return = static::classicExtract($array, str_replace("{a}", "{[a-zA-Z0-9-_. ]}", $path));
        } else {
            $return = Hash::extract($array, $path);
        }
    }
    if ($filter && is_array($return)) {
        $return = Hash::filter($return);
    }
    return $return;
}