Извлечение нескольких значений массива с извлечением
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
Ответы
Ответ 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;
}