$row) {
if (!array_key_exists($columnName, $row)) {
return $result;
}
if ((Qs_Array::FETCH_UNIQUE & $fetchMode) && in_array($row[$columnName], $result)) {
continue;
}
if ((Qs_Array::FETCH_ASSOC & $fetchMode)) {
$result[$key] = $row[$columnName];
} else {
$result[] = $row[$columnName];
}
}
return $result;
}
public static function sum(array $list, $columnName = false)
{
if (false !== $columnName) {
$list = Qs_Array::fetchCol($list, $columnName);
}
return array_sum($list);
}
public static function fetchPairs(array $list, array $bind = array())
{
$result = array();
if (empty($list)) {
return $result;
}
$firstRow = current($list);
if (empty($bind)) {
$bind = array_keys($firstRow);
}
if (count($bind) < 2) {
throw new Qs_Exception('List or bind argument must have 2 or more values for each row');
}
$keyName = array_shift($bind);
$valueName = array_shift($bind);
foreach ($list as $row) {
$result[$row[$keyName]] = $row[$valueName];
}
return $result;
}
public static function group($list, $columns, $exclude = null)
{
$result = array();
$columns = (array) $columns;
if (null === $exclude) {
$exclude = $columns;
}
foreach ($list as $row) {
$parts = array();
foreach ($columns as $column) {
if (static::AUTOINCREMENT === $column) {
$parts[] = count(static::get($result, $parts, []));
} else {
$parts[] = $row[$column];
}
}
Qs_Array::set($result, $parts, Qs_Array::excludeArray($row, $exclude));
}
return $result;
}
public static function isAssoc($array)
{
$count = count($array);
for ($i = 0; $i < $count; $i++) {
if (!array_key_exists($i, $array)) {
return true;
}
}
return false;
}
public static function mergeAssoc()
{
$arguments = func_get_args();
$argumentsCount = func_num_args();
if ($argumentsCount < 2) {
return false;
}
$array = array();
for ($i = 0; $i < $argumentsCount; $i++) {
foreach ($arguments[$i] as $k => $v) {
$array[$k] = $v;
}
}
return $array;
}
public static function mergeDiff($array1, $array2)
{
return array_merge($array1, array_diff_key($array2, $array1));
}
public static function diffRecursive($array1, $array2)
{
foreach ($array1 as $key => $value) {
if (is_array($value)) {
if (@!is_array($array2[$key])) {
$difference[$key] = $value;
} else {
$new_diff = Qs_Array::diffRecursive($value, $array2[$key]);
if (!empty($new_diff)) {
$difference[$key] = $new_diff;
}
}
} elseif ($value != @$array2[$key]) {
$difference[$key] = $value;
}
}
return !isset($difference) ? array() : $difference;
}
/**
* @static
* @param $firstArray mixed
* @param $secondArray mixed
* @return array
*/
public static function mergeRecursive($firstArray, $secondArray)
{
if (is_array($firstArray) && is_array($secondArray)) {
foreach ($secondArray as $key => $value) {
if (isset($firstArray[$key])) {
$firstArray[$key] = Qs_Array::mergeRecursive($firstArray[$key], $value);
} else {
$firstArray[$key] = $value;
}
}
} else {
$firstArray = $secondArray;
}
return $firstArray;
}
/**
* Array sorting
*
* $data, multidim array
* $keys, array(array(key => col1, sort => desc), array(key => col2, type => numeric))
*
* @param array $data
* @param array $keys
* @return array
*/
public static function multisort($data, $keys)
{
// List As Columns
$cols = array();
foreach ($data as $key => $row) {
foreach ($keys as $k){
$cols[$k['key']][$key] = $row[$k['key']];
}
}
// List original keys
$idKeys = array_keys($data);
// Sort Expression
$i = 0;
$sort = '';
foreach ($keys as $k) {
if ($i > 0) {
$sort .= ', ';
}
$sort .= '$cols[\'' . $k['key'] . '\']';
if (isset($k['sort'])) {
$sort .= ', SORT_' . strtoupper($k['sort']);
}
if (isset($k['type'])) {
$sort .= ', SORT_' . strtoupper($k['type']);
}
$i++;
}
$sort .= ', $idKeys';
$sort = 'array_multisort(' . $sort . ');';
eval($sort);
// Rebuild Full Array
$result = array();
foreach($idKeys as $idKey) {
$result[$idKey] = $data[$idKey];
}
return $result;
}
/**
* @static
* @param array $array
* @param string $field
* @param mixed $default
* @return mixed
* @throws Qs_Exception
*/
public static function get($array, $field, $default = null)
{
$array = (array) $array;
if (false !== $field && null !== $field) {
if (is_array($field)) {
$parts = $field;
} else {
$field = str_replace(']', '', '' . $field);
$parts = explode('[', $field);
}
while (null !== ($name = array_shift($parts))) {
if (!array_key_exists($name, $array)) {
return $default;
}
$array = $array[$name];
}
}
return $array;
}
public static function set(&$array, $field, $value)
{
if (false !== $field) {
if (is_array($field)) {
$parts = $field;
} else {
$field = str_replace(']', '', $field);
$parts = explode('[', $field);
}
if (null !== ($name = array_shift($parts))) {
if (empty($parts)) {
$array[$name] = $value;
} elseif (!array_key_exists($name, $array) || !is_array($array[$name])) {
$array[$name] = array();
}
Qs_Array::set($array[$name], $parts, $value);
}
} else {
$array = $value;
}
}
public static function remove(&$array, $field)
{
if (false !== $field) {
if (is_array($field)) {
$parts = $field;
} else {
$field = str_replace(']', '', $field);
$parts = explode('[', $field);
}
if (($name = array_shift($parts))) {
if (empty($parts)) {
unset($array[$name]);
} elseif (array_key_exists($name, $array)) {
Qs_Array::remove($array[$name], $parts);
}
}
} else {
unset($array);
}
}
public static function excludeArray($array1, $array2)
{
foreach ($array2 as $keyName) {
if (is_array($keyName)) {
$array1 = Qs_Array::excludeArray($array1, $keyName);
} elseif (array_key_exists($keyName, $array1)) {
unset($array1[$keyName]);
}
}
return $array1;
}
public static function excludeKey()
{
$args = func_get_args();
return call_user_func_array('Qs_Array::exclude', $args);
}
/**
* @static
* @deprecated function deprecated in Release 3.0. Use excludeKey
* @return bool|mixed
*/
public static function exclude()
{
if (func_num_args() < 2) {
return false;
}
$args = func_get_args();
$array = array_shift($args);
$array = Qs_Array::excludeArray($array, $args);
return $array;
}
public static function excludeValue()
{
if (func_num_args() < 2) {
return false;
}
$args = func_get_args();
$array = array_shift($args);
$array = Qs_Array::excludeValues($array, $args);
return $array;
}
public static function excludeValues(array $array, array $values)
{
foreach ($values as $value) {
if (false !== ($index = array_search($value, $array))) {
unset($array[$index]);
}
}
return $array;
}
public static function collapse(array $array, $belongsTo = '')
{
$result = array();
foreach ($array as $key => $value) {
$itemBelongsTo = $belongsTo . (empty($belongsTo) ? $key : '[' . $key . ']');
if (is_array($value)) {
$result = array_merge($result, Qs_Array::collapse($value, $itemBelongsTo));
} else {
$result[$itemBelongsTo] = $value;
}
}
return $result;
}
public static function expand(array $array)
{
$result = array();
foreach ($array as $key => $value) {
Qs_Array::set($result, $key, $value);
}
return $result;
}
/**
* Swap 2 elements in array preserving keys
*
* @param array $array
* @param mixed $key1
* @param mixed $key2
* @return array
*/
public static function swap($array, $key1, $key2)
{
if (!is_array($array) || empty($array) || !array_key_exists($key1, $array)
|| !array_key_exists($key2, $array)
) {
return $array;
}
$value1 = $array[$key1];
$value2 = $array[$key2];
$result = array();
foreach($array as $key => $value) {
if ((string) $key == (string) $key1) {
$key = $key2;
$value = $value2;
} else if ((string) $key == (string) $key2) {
$key = $key1;
$value = $value1;
}
$result[$key] = $value;
}
return $result;
}
/**
* Move an element inside an array preserving keys
* $relpos should be like -1, +2...
*
* @param array $array
* @param int $key
* @param int $relpos
* @return array
*/
public static function move($array, $key, $relpos)
{
if (!is_array($array) || empty($array) || !array_key_exists($key, $array) || !$relpos) {
return $array;
}
$from = Qs_Array::keyPos($key, $array);
if ($from === false) {
return $array;
}
$to = $from + $relpos + ($relpos > 0 ? 1 : 0);
$length = count($array);
if ($to >= $length) {
$val = $array[$key];
unset($array[$key]);
$array[$key] = $val;
} else {
if ($to < 0) {
$to = 0;
}
$new = array();
$x = 0;
foreach ($array as $i => $v) {
if ($x++ == $to) {
$new[$key] = $array[$key];
}
if ($i !== $key) {
$new[$i]=$v;
}
}
$array = $new;
}
return $array;
}
/**
* Get a key position in array
*
* @param mixed $key
* @param array $array
* @return integer
*/
public static function keyPos($key, $array)
{
$position = 0;
foreach ($array as $i => $v) {
if ($key === $i) {
return $position;
}
$position++;
}
return false;
}
/**
* Return key by position
*
* @param int $position
* @param array $array
* @return integer
*/
public static function keyByPos($position, $array)
{
$x = 0;
foreach ($array as $i => $v) {
if ($position == $x++) {
return $i;
}
}
return false;
}
public static function implodeLast($separator, $lastSeparator, $array)
{
$arraySize = count($array);
$separators = array();
if ($arraySize > 2) {
$separators = array_fill(0, $arraySize - 2, $separator);
}
$separators[] = $lastSeparator;
return Qs_Array::implode($separators, $array);
}
public static function implode()
{
$countArguments = func_num_args();
$arguments = func_get_args();
if ($countArguments == 2 && is_array($arguments[0])) {
$string = '';
$separators = array_values($arguments[0]);
$elements = array_values($arguments[1]);
$countSepatarots = count($separators);
$countElements = count($elements);
for ($i = 0; $i < $countElements; $i++) {
$string .= (0 == $i ? '' : $separators[($i - 1) % $countSepatarots]) . $elements[$i];
}
return $string;
}
return call_user_func_array('implode', $arguments);
}
/**
* Convert associated array to indexed array with associated items
* @static
* @param array $array Associated array
* @param string $keyName
* @param string $valueName
* @return array Indexed array
*/
public static function assocToIndex(array $array, $keyName, $valueName)
{
$result = array();
foreach ($array as $key => $value) {
$result[] = array($keyName => $key, $valueName => $value);
}
return $result;
}
/**
* Return array containing values from $source specified by $map ([$destination] => $source)
*
* Example:
*
* $values = array('map', 'class' => 'Qs_Array', 'framework' => 'qsf2', 'ver' => array(2, 0));
* $map = array(
* 'function' => 0,
* 'class',
* 'framework' => array('source' => 'framework', 'callback' => 'strtoupper'),
* 'version' => 'ver[0]',
* );
* $result = Qs_Array::map($values, $map);
* // Return: array('function' => 'map', 'class' => 'Qs_Array', 'framework' => 'QSF2', 'version' => 2)
*
* @static
* @param array $values Source array
* @param array $map Array of pairs ([$destination] => string|array $source).
* @return array
*/
public static function map($values, $map)
{
$result = array();
foreach ($map as $destination => $source) {
$sourceKey = null;
$callback = null;
if (is_array($source)) {
$sourceKey = (isset($source['source'])) ? $source['source'] : $destination;
$callback = (isset($source['callback']) && is_callable($source['callback']))
? $source['callback']
: null;
} else {
$sourceKey = $source;
$destination = is_int($destination) ? $sourceKey : $destination;
}
if (is_array($sourceKey) || (is_string($sourceKey) && false !== strpos($sourceKey, '['))) {
$value = self::get($values, $sourceKey, null);
} else {
$value = array_key_exists($sourceKey, $values) ? $values[$sourceKey] : null;
}
$result[$destination] = (isset($value) && isset($callback)) ? call_user_func($callback, $value) : $value;
}
return $result;
}
/**
* Extract value from tree
* @static
* @param array $tree
* @param string $valueField
* @return array
*/
public static function treeValues(array $tree, $valueField = 'value')
{
$result = array();
self::_treeValues($tree, $valueField, $result);
return $result;
}
/**
* @internal
* @static
* @param array $tree
* @param string $valueField
* @param array $result
* @return void
*/
protected static function _treeValues(array $tree, $valueField, array &$result)
{
foreach ((array) $tree as $node) {
if (array_key_exists($valueField, $node)) {
$result[] = $node[$valueField];
}
if (!empty($node['sub'])) {
self::_treeValues($node['sub'], $valueField, $result);
}
}
return;
}
/**
* Build tree from the array according to $idField and $parentIdFiled
* @param array $list Two level array with source values
* @param array $fields Field what will be copied to each node using Qs_Array::map()
* @param string $idField
* @param string $parentIdField
* @return array
*/
public static function buildTree(array $list, $fields = array('id', 'title'),
$idField = 'id', $parentIdField = 'parentId')
{
$result = array();
self::_buildNodeSub($list, $result, 0, $fields, $idField, $parentIdField);
return $result;
}
protected static function _buildNodeSub(array &$list, array &$parentSub, $parentId = 0,
$fields, $idField, $parentIdField)
{
foreach ($list as $key => $row) {
if ($parentId == $row[$parentIdField]) {
$node = self::map($row, $fields);
unset($list[$key]);
$node['sub'] = array();
self::_buildNodeSub($list, $node['sub'], $row[$idField], $fields, $idField, $parentIdField);
if (empty($node['sub'])) {
unset($node['sub']);
}
$parentSub[$row[$idField]] = $node;
}
}
return;
}
/**
* @param array $tree
* @param $parentValue
* @param string $parentKey default 'id'
* @return array|null
*/
public static function treeBranch(array $tree, $parentValue, $parentKey = 'id')
{
if (0 == $parentValue) {
return $tree;
}
foreach ($tree as $node) {
if ($node[$parentKey] == $parentValue) {
return $node['sub'];
}
if (!empty($node['sub'])) {
if (null !== ($subTree = self::treeBranch($node['sub'], $parentValue, $parentKey))) {
return $subTree;
}
}
}
return null;
}
/**
* @static
* @param $array
* @param $index int
* @param $value mixed
*/
public static function insertAfter(&$array, $index, $value)
{
$array = array_merge(array_slice($array, 0, $index + 1), (array) $value, array_slice($array, $index + 1));
}
/**
* @static
* @param array $array
* @param $afterKey
* @param $insertKey
* @param $insertValue
*/
public static function insertAfterAssoc(array &$array, $afterKey, $insertKey, $insertValue)
{
$result = array();
foreach ($array as $key => $value) {
$result[$key] = $value;
if ($key == $afterKey) {
$result[$insertKey] = $insertValue;
}
}
$array = $result;
}
/**
* Example:
*
* $array = array('map', 'class' => 'Qs_Array', 'ver' => array('qsf3', 'flat'));
* $result = Qs_Array::flatten($array);
* // Return: array (0 => 'map', 1 => 'Qs_Array', 2 => 'qsf3', 3 => 'flat);
*
*
* @static
* @param array $array
* @return array
*/
public static function flatten(array $array)
{
$result = array();
array_walk_recursive($array, function ($value) use (&$result) { $result[] = $value; });
return $result;
}
/**
*
* $array = array('name' => 'Philip Fry', 'phone' => '(067) 111-1111', 'address' => array('city' => 'New York', 'state' => 'NY', 'zip' => 90001));
*
* $result = Qs_Array::flatten($array);
* // Return: array('name' => 'Philip Fry', 'phone' => '(067) 111-1111', 'address[city]' => 'New York', 'address[state]' => 'NY', 'address[zip]' => 90001)
*
* $result = Qs_Array::flatten($array, true);
* // Return: array('name' => 'Philip Fry', 'phone' => '(067) 111-1111', 'addressCity' => 'New York', 'addressState' => 'NY', 'addressZip' => 90001)
*
*
* @static
* @param array $array
* @param bool $friendlyKeys
* @param null $belongsTo
* @return array
*/
public static function flattenAssoc(array $array, $friendlyKeys = false, $belongsTo = null)
{
$result = array();
foreach ($array as $key => $value) {
if (null !== $belongsTo) {
if ($friendlyKeys) {
$key = $belongsTo . ucfirst($key);
} else {
$key = $belongsTo . '[' . $key . ']';
}
}
if (is_array($value)) {
$result += static::flattenAssoc($value, $friendlyKeys, $key);
} else {
$result[$key] = $value;
}
}
return $result;
}
/**
* @static
* @param array $list Associative list of nodes array(id => array(), ...)
* @param string $parentIdField [OPTIONAL]
* @param callable|null $callback [OPTIONAL]
* @return array Result tree
*/
public static function assocToTree(array $list, $parentIdField = 'parentId', $callback = null)
{
$root = array();
foreach ($list as $id => $node) {
if (null !== $callback) {
if (false === $callback($list[$id])) {
continue;
}
}
if ($node[$parentIdField]) {
if (isset($list[$node[$parentIdField]])) {
$list[$node[$parentIdField]]['sub'][$id] = &$list[$id];
}
} else {
$root[$id] = &$list[$id];
}
}
return $root;
}
/**
* @static
* @param array $tree
* @param callable $callback
* @return void
*/
public static function treeWalk(array &$tree, $callback)
{
foreach ($tree as $index => $node) {
if (false === $callback($tree[$index])) {
unset($tree[$index]);
continue;
}
if (isset($tree[$index]['sub'])) {
self::treeWalk($tree[$index]['sub'], $callback);
}
}
return;
}
}