Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Функциональное разделение массивов
Форумы портала PHP.SU » PHP » Пользовательские функции » Функциональное разделение массивов

Страниц (1): [1]
 

1. EuGen - 04 Февраля, 2013 - 17:09:28 - перейти к сообщению
Поскольку часто бывает нужно превосходить возможности array_filter, которая лишь фильтрует массив по некоторой функции, а писать каждый раз array_map - это не dry-подход, я использую простую функцию
PHP:
скопировать код в буфер обмена
  1. function array_split($rgData, $fnCallback, $bStoreGroup=false)
  2. {
  3.    if(!is_callable($fnCallback))
  4.    {
  5.       return null;
  6.    }
  7.    $rgResult = array();
  8.    foreach($rgData as $mValue)
  9.    {
  10.       $mFunctional = call_user_func($fnCallback, $mValue);
  11.       $sKey = $bStoreGroup?$mFunctional:serialize($mFunctional);
  12.       if(is_object($sKey))
  13.       {
  14.          try
  15.          {
  16.             $sKey=(string)$sKey;
  17.          }
  18.          catch(Exception $rException)
  19.          {
  20.             return null;
  21.          }
  22.       }
  23.       elseif(!is_scalar($sKey))
  24.       {
  25.          return null;
  26.       }
  27.       if(array_key_exists($sKey, $rgResult))
  28.       {
  29.          $rgResult[$sKey][]=$mValue;
  30.       }
  31.       else
  32.       {
  33.          $rgResult[$sKey] = array($mValue);
  34.       }
  35.    }
  36.    return $bStoreGroup?$rgResult:array_values($rgResult);
  37. }

Все, что она делает - применяет callback ко всем элементам массива и возвращает результирующий массив, в котором данные сгруппированы в соответствии со значениями этой функции. При этом есть возможность сохранения значения группирующей функции в ключах результирующего массива. Разумеется, это получится сделать, если эта функция возвращает скаляр, либо объект, который имеет метод строкового представления. В иных случаях при использовании опции возврата ключей эта функция даст null.
Пример:
PHP:
скопировать код в буфер обмена
  1. class Foo
  2. {
  3.    function calc($mParam)
  4.    {
  5.       return abs($mParam);
  6.    }
  7. }
  8. $rFoo = new Foo();
  9. $rgData= array("2", "-1", "1", "-2");
  10. //var_dump(array_split($rgData, array($rFoo, "calc"), true));
2. DeepVarvar - 04 Февраля, 2013 - 17:43:46 - перейти к сообщению
EuGen пишет:
$mFunctional = $fnCallback($mValue);
Я честно забыл с какой версии доступно такое обращение именно к функциям?
3. OrmaJever - 04 Февраля, 2013 - 17:55:30 - перейти к сообщению
DeepVarvar пишет:
Я честно забыл с какой версии доступно такое обращение именно к функциям?

А?! 5.3 ?
4. esterio - 04 Февраля, 2013 - 17:56:14 - перейти к сообщению
DeepVarvar
Кажется такое и в 4-ой версии доступно было. Только интересует такое - такой ж подход нельзя применит к обьектам? тоесть мб лучше call_user_func?
5. EuGen - 04 Февраля, 2013 - 18:00:15 - перейти к сообщению
Еще с php 4. По-хорошему, нужно еще делать проверку is_callable и возвращать null, если была неудача.
И - да, код можно улучшить с помощью call_user_func. Хотя у меня есть вариант рекурсивного вызова, когда группировка ведется по нескольким значениям - с использованием такого подхода. Позже предоставлю и его.
upd. "рекурсивный" вариант оказался неактуален, поскольку применяется к двумерным массивам и может быть заменен соответствующим callback-вызовом для этой функции.

 

Powered by ExBB FM 1.0 RC1