Apply array_map on column of the array - php

I was trying to get a solution to speed up the process of PHP.
We are running into execution time issues on a specific page.
We have an array with around 10.000 rows and we need to apply several callback functions on some of the columns of that array.
What is the best way and the fastest execution possible to go over an array and only apply a callback on several columns.
<?php
$records = [
['id' => 2135, 'first_name' => 'John', 'price' => 1000, 'unit' => 5, 'discount' => 30],
['id' => 3245, 'first_name' => 'Sally', 'price' => 2000, 'unit' => 8, 'discount' => 80],
['id' => 5342, 'first_name' => 'Jane', 'price' => 4000, 'unit' => 5, 'discount' => 34],
['id' => 5623, 'first_name' => 'Peter', 'price' => 1500, 'unit' => 4, 'discount' => 25]
];
function simpleMultiply($value)
{
return $value * 2;
}
$applyToColumn = ['price','unit','discount'];
// $expectedRecords = array_map('simpleMultiply', array_column($records, 'id'));
$expectedRecords = [
['id' => 2135, 'first_name' => 'John', 'price' => 2000, 'unit' => 10, 'discount' => 60],
['id' => 3245, 'first_name' => 'Sally', 'price' => 4000, 'unit' => 16, 'discount' => 160],
['id' => 5342, 'first_name' => 'Jane', 'price' => 8000, 'unit' => 10, 'discount' => 68],
['id' => 5623, 'first_name' => 'Peter', 'price' => 3000, 'unit' => 8, 'discount' => 50]
];
?>

array_column is an expensive operation if the array is large, because it has to create an entirely new array. Calling it repeatedly for different columns will multiply that expense. I suggest you just use a simple foreach loop.
$expectedRecords = array();
foreach ($records as $r) {
foreach ($applyToColumn as $col) {
$r[$col] = simpleMultiply($r[$col]);
}
$expectedRecords[] = $r;
}
If you can modify the original $records instead of creating a new $expectedRecords, you can use a reference in the first foreach.
foreach ($records as &$r) {
foreach ($applyToColumn as $col) {
$r[$col] = simpleMultiply($r[$col]);
}
}

You can wrap the result set in an iterator (or a generator, which looks rather similar to an iterator) that modifies the current row before returning it as the iteration result, e.g.
<?php
class Foo extends IteratorIterator {
public function current() {
$rv = parent::current();
if ( $rv ) {
// ... and more checks here ....
// this example just assumes the fields/elements exist
$rv['x'] *= 17;
return $rv;
}
}
}
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'localonly', 'localonly', array(
PDO::ATTR_EMULATE_PREPARES=>false,
PDO::MYSQL_ATTR_DIRECT_QUERY=>false,
PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION
));
setup($pdo);
// the point is not to have the complete result set in memory
// see: e.g. php.net/mysqlinfo.concepts.buffering (or whatever database you use ;-) )
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$result = new Foo( $pdo->query('SELECT x,y FROM sofoo') );
foreach( $result as $row ) {
echo join(', ', $row), PHP_EOL;
}
function setup($pdo) {
$pdo->exec('
CREATE TEMPORARY TABLE sofoo(
id int auto_increment, # I just throw this in casually....
x int,
y int,
primary key(id)
)
');
$stmt = $pdo->prepare('INSERT INTO sofoo (x,y) VALUES (?,?)');
foreach( range(1,5) as $x ) {
$stmt->execute( array($x, $x*13) );
}
}
or (without most of the boilerplate, using a generator - and invoking the anonymous function immediately)
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$result = (function($iter) {
foreach( $iter as $row ) {
$row['x'] *= 17;
yield $row;
}
})($pdo->query('SELECT x,y FROM sofoo') );
foreach( $result as $row ) {
echo join(', ', $row), PHP_EOL;
}
You can build this "system" arbitrarily complex. Maybe passing the field names and functions to modify the elements to the generator like
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$result = my_generator(
$pdo->query('SELECT x,y FROM sofoo'),
array('x'=>function($e) { return $e*17; })
);
foreach( $result as $row ) {
echo join(', ', $row), PHP_EOL;
}
function my_generator($iter, $modifiers) {
foreach( $iter as $row ) {
foreach( $modifiers as $field=>$func) {
$row[$field] = $func($row[$field]);
}
yield $row;
}
}
or add some chaining mechanism so that multiple functions can modify the same field. Or passing the complete row to the functions so they can change the structure as well. Or ... or ...

Related

Making changes on a different property of recursive function

I'm currently developing this code that traverse a hierarchical array which should compute the sub-total of a property called cur_compensation. My issue is that the changes I do is not getting save
private function computeSubTotal($hierarchy){
foreach($hierarchy["_children"] as $key => $value){
if(isset($value["_children"]))
{
static::computeSubTotal($value);
}
else{
foreach($hierarchy["_children"] as $employee){
$employee_cur_compensation = $employee["cur_compensation"] ?? 0;
if (!isset($hierarchy["cur_compensation"])) {
$hierarchy["cur_compensation"] = 0;
}
$hierarchy["cur_compensation"] += $employee_cur_compensation;
}
return $hierarchy;
}
}
return $hierarchy;
}
This is the function so what it does it goes to the deepest node, the deepest node is a value that does not have any _children which mean it doesn't have any sub department (the hierarchy is sorted that the sub department are always on top)
The issue I have, once it reaches the bottom it computes the cur_compensation by looping through the employees of that department and adding it on the department "cur_compensation" property.
The issue is that, it doesn't save any of my changes.
So the purpose of the function is to add up the 'cur_compensation' of each employee/sub-department.
For example ->
$rows = array(
array(
'name' => "Main",
'id' => 1,
'parent_id' => 0,
'cur_compensation' => 0,
'_children' => array(
array(
'name' => "Dept A",
'id' => 2,
'parent_id' => 1),
),
array(
'name' => "Dept B",
'id' => 3,
'parent_id' => 1,
'_children' => array(
array(
'name' => "Dept C",
'cur_compensation' => 30000,
'id' => 4,
'parent_id' => 3),
array(
'name' => "Employee C",
'cur_compensation' => 30000,
'id' => 7,
'parent_id' => 3
)
)),
array(
'name' => "Employee A",
'cur_compensation' => 20000,
'id' => 5,
'parent_id' => 1
),
array(
'name' => "Employee B",
'cur_compensation' => 30000,
'id' => 6,
'parent_id' => 1
)
)
)
);
The result I want to get would be:
$rows = array(
array(
'name' => "Main",
'id' => 1,
'parent_id' => 0,
'cur_compensation' => 120000,
'_children' => array(
array(
'name' => "Dept A",
'id' => 2,
'cur_compensation' => 0,
'parent_id' => 1),
),
array(
'name' => "Dept B",
'id' => 3,
'parent_id' => 1,
'cur_compensation' => 60000,
'_children' => array(
array(
'name' => "Dept C",
'cur_compensation' => 30000,
'id' => 4,
'parent_id' => 3),
array(
'name' => "Employee C",
'cur_compensation' => 30000,
'id' => 7,
'parent_id' => 3
)
)),
array(
'name' => "Employee A",
'cur_compensation' => 30000,
'id' => 5,
'parent_id' => 1
),
array(
'name' => "Employee B",
'cur_compensation' => 30000,
'id' => 6,
'parent_id' => 1
)
)
)
);
So you would notice that Main and Dept B got the cur_compensation based on the _children property
There's a few things to make note on here - so I'm going to add comments to your existing code, then provide an example of how you could change it.
(I've formatted the code in each case)
class Example {
// filler code so that we can call
public function process($array){
return $this->computeSubTotal($array);
}
private function computeSubTotal($hierarchy) {
// we're not checking whether "_children" property exists before looping on it
foreach ($hierarchy["_children"] as $key => $value) {
if (isset($value["_children"])) {
// we're calling the method, but not doing anything with the return value.
static::computeSubTotal($value);
// we can set the original array value instead which will provide a modified copy
// this can be resolved by uncommenting the line below
// $hierarchy["_children"][$key] = static::computeSubTotal($value);
// also note that if this "child" doesn't have any *grand*children
// then we won't get an updated value due to how this is structured
// to fix this, you could remove the else wrapping so that the code
// below runs always
} else {
// double looping - we're already looping this array
// this will cause the end value to increase exponentially
foreach ($hierarchy["_children"] as $employee) {
$employee_cur_compensation = $employee["cur_compensation"] ?? 0;
if (!isset($hierarchy["cur_compensation"])) {
$hierarchy["cur_compensation"] = 0;
}
$hierarchy["cur_compensation"] += $employee_cur_compensation;
}
// returning whole array inside the loop is not ideal
// we have already adjusted the main array
// comment out this return to prevent that from happening
return $hierarchy;
}
}
return $hierarchy;
}
}
$example = new Example;
// calling this on $rows won't give us anything back
// since $rows doesn't contain the property "_children"
$rows = $example->process($rows);
// in this case, you would want to process each array result
// only on this primary array
foreach($rows as $index => $value){
$rows[$index] = $example->process($value);
}
echo json_encode($rows, JSON_PRETTY_PRINT);
Taking those comments into account, you would end up with something like this:
private function computeSubTotal($hierarchy) {
// we're not checking whether "_children" property exists before looping on it
foreach ($hierarchy["_children"] as $key => $value) {
if (isset($value["_children"])) {
$hierarchy["_children"][$key] = static::computeSubTotal($value);
}
// double looping - we're already looping this array
// this will cause the end value to increase exponentially
foreach ($hierarchy["_children"] as $employee) {
$employee_cur_compensation = $employee["cur_compensation"] ?? 0;
if (!isset($hierarchy["cur_compensation"])) {
$hierarchy["cur_compensation"] = 0;
}
$hierarchy["cur_compensation"] += $employee_cur_compensation;
}
}
return $hierarchy;
}
That's closer but still, it's not quite correct due to the double looping.
I've made a simpler version that is hopefully easy to follow:
private function computeSubTotal($hierarchy) {
if (!isset($hierarchy["_children"])) {
return $hierarchy;
}
// define this outside the loop for clarity
if (!isset($hierarchy["cur_compensation"])) {
$hierarchy["cur_compensation"] = 0;
}
foreach ($hierarchy["_children"] as $key => $value) {
// don't need to check for "_children" property
// as it's now handled in this function
$updated = static::computeSubTotal($value);
// reference the $updated array to increment
// the "cur_compensation" field
$hierarchy["cur_compensation"] += $updated["cur_compensation"] ?? 0;
// update original array
$hierarchy["_children"][$key] = $updated;
}
return $hierarchy;
}
// call like
foreach ($rows as $index => $value) {
$rows[$index] = static::computeSubTotal($value);
}
You will still need to change how you're passing the $rows variable due to it now containing a "_children" property (as shown in the examples) - either pass each element or add additional logic in that function to handle that.
You need to pass the array as a reference.
https://www.php.net/manual/en/language.references.pass.php
PHP passes the array to the function as a pointer, but when you try to update the array, PHP first makes a full copy of the array and updates the copy instead of the original.
Change your function signature to the following and it should be good.
private function computeSubTotal(&$hierarchy){
P.S. You are calling computeSubTotal statically, but the function is not static itself.

convert normal array in nested array with php

I have a hierarchical database table like below
ID Name Subcategory ParentID
1 ABC 0
2 DEF QFE 0
3 QFE XYZ 2
4 XYZ MNJ 3
From Thant I have got PHP array like below
$array_name = array(
array('ID' => '1', 'Name' => 'ABC', 'Subcategory' => '', 'ParentID' => '0'),
array('ID' => '2', 'Name' => 'DEF', 'Subcategory' => 'QFE', 'ParentID' => '0'),
array('ID' => '3', 'Name' => 'QFE', 'Subcategory' => 'XYZ', 'ParentID' => '2'),
array('ID' => '4', 'Name' => 'XYZ', 'Subcategory' => 'MNJ', 'ParentID' => '3')
);
but I want array like below
$array_name = array(
array('ID' => '1', 'Name' => 'ABC', 'Subcategory' => '', 'ParentID' => '0'),
array('ID' => '2', 'Name' => 'DEF', 'Subcategory' => array('ID' => '3', 'Name' => 'QFE', 'Subcategory' => array('ID' => '4', 'Name' => 'XYZ', 'Subcategory' => 'MNJ', 'ParentID' => '3'), 'ParentID' => '2'), 'ParentID' => '0'),
);
I want a function which checks is that row have some Subcategory or not and if a row has Subcategory then get that subcategory row as an array and make one array with all category and Subcategory
for that, I have tried to make a function which is given below
function find_subcategory($ID,$con){
$table_name ="SELECT * FROM `table_name` WHERE `parent_id` = '$ID'";
$table_name_result = mysqli_query($con,$table_name);
$category_array = array();
if(mysqli_num_rows($table_name_result)) {
while($row = mysqli_fetch_assoc($table_name_result)) {
$Subcategory= $row['Subcategory'];
$ID = $row['ID'];
if ($Subcategory== '') {
$find_subcategory = find_subcategory($ID,$con);
$row['Subcategory'] = $find_subcategory;
$category_array[] = $row;
}else{
$category_array[] = $row;
}
}
}
return json_encode(array('tbl_category'=>$category_array));
}
but this function is not working to get all the subcategories of one category.
can anybody help me with this
Rather than create a recursive routine, which executes the SQL for each level, this instead reads all of the categories in and them assembles them into the hierarchy.
Note that it reads them in reverse order so that when it assembles them, each subcategory is always read before the parent (More details in code comments)...
$table_name ="SELECT * FROM `category` ORDER BY parent_id DESC, id desc";
$table_name_result = mysqli_query($con,$table_name);
$categories = mysqli_fetch_all($table_name_result, MYSQLI_ASSOC);
$output= [];
foreach ( $categories as $category) {
// If there is a parent for this item
if ( !empty ($category['parent_id']) ) {
// Set basic details
$output[$category['parent_id']]['Subcategory'][$category['id']] = $category;
// If there is already some data (subcategories)
if ( isset($output[$category['id']]) ){
// Copy subcategories
$output[$category['parent_id']]['Subcategory'][$category['id']] +=
$output[$category['id']];
// Remove old node
unset ( $output[$category['id']] );
}
}
else {
// Add in category data (allow for existing data to be added
$output[$category['id']] = $category + ($output[$category['id']]??[]);
}
}
I successfully implemented and tested a recursive routine to solve this. However, for performance reasons I had to decouple the access to the database from the recursive call.
First, you fetch your query into an array as you already have and then recursively rearrange the elements so that the keys are nested in the proper order.
Pretty much of the explanations I'd like to put here are put as comments in the code.
$array_name = array(
array('ID' => '1', 'Name' => 'ABC', 'Subcategory' => '', 'ParentID' => '0'),
array('ID' => '2', 'Name' => 'DEF', 'Subcategory' => 'QFE', 'ParentID' => '0'),
array('ID' => '3', 'Name' => 'QFE', 'Subcategory' => 'XYZ', 'ParentID' => '2'),
array('ID' => '4', 'Name' => 'XYZ', 'Subcategory' => 'MNJ', 'ParentID' => '3'),
array('ID' => '5', 'Name' => 'XYY', 'Subcategory' => 'MNJ', 'ParentID' => '1')
);
// recreate nested array
function get_nested_array($arr) {
$new_arr = array(); // new array to collect each top level element with nesting
foreach ($arr as $key => $value) {
// only top level elements would appear here as they would not be nested
if($value['ParentID'] == '0') {
array_push($new_arr, get_nested_item($value, $arr));
}
}
return $new_arr;
}
// recursive function to perform nesting on each element
function get_nested_item($hay, $stack) {
foreach ($stack as $key => $value) {
if ($hay['ID'] == $value['ParentID']) {
$index = get_key($hay, $stack);
// reduce $stack size by removing the HAY from the STACK
// recursion terminates when $stack size is 0
$stack = $index >= 0 ? array_splice($stack, $index) : [];
// update subcategory of the found nesting
$hay['Subcategory'] = get_nested_item($value, $stack);
}
}
return $hay;
}
// get the position of $hay in a $stack using the ID
function get_key($hay, $stack) {
foreach ($stack as $key => $value) {
if($hay['ID'] == $value['ID']) return $key;
}
return -1;
}
// print array so that it understandable
function print_array($arr) {
foreach ($arr as $key => $value) {
print_r($value);
echo "<br>";
}
}
// Test case
// print array before nesting
print_array($array_name);
echo"<br>";
// print array after nesting
$new_array = get_nested_array($array_name);
print_array($new_array);

Call each value from array of an object

I have function in class, which returns array with 4 3-4 rows. I have to use each value from related row in table values. I can print builded function atrray, and can print on parent file, but can not get values for elements for each row. Here is my class file:
<?php
class Anyclass
{
public function $monthly($array)
{
.
.
.
}
public function myfunction($array)
{
foreach ($ShowMonths as $duration) {
$array['Credit']['downpayment'] = 0;
$array['Credit']['duration'] = $duration;
$monthly = $this->monthly($array);
$Table['Options'][] = array(
'downpayment' => $array['Credit']['downpayment'],
'duration' => $array['Credit']['duration'],
'monthly' => $monthly,
'total' => $monthly * $array['Credit']['duration'] + $array['Credit']['downpayment']
);
}
print_r($Table);
}
}
Here is my main file
include_once('mypathtofile/FileWithClass.php');
$Cll = new NewOne();
$array = array(
'Rule' => array(
'rule_id' => 1,
'rule_name' => 'Mobile phones',
'interest' => 0.01,
'comission' => 0.01,
'best_offer_downpayment' => 0.5,
'best_offer_duration' => 6
),
'Product' => array(
'product_id' => 1,
'category_id' => 1,
'manufacturer_id' => 1,
'product_price' => 500
),
'Credit' => array(
'downpayment' => 100,
'duration' => 6
)
);
$prtst = $Cll->myfunction($array);
How can I call each elemet for each row?
I'm not sure what you are trying to do, but if you need to get each value in a multidimensional array - you can use recursion:
function get_value($array){
foreach($array as $item){
if(is_array($item)){
get_value($item);
} else {
echo $item;
}
}
}

Populating database field with multiple value

I am working on populating the database tables. The table have fields which some of them are enum.
Consider a user which have a field status , whose values can be active, inactive etc. Assume we can modify the configuration values and running the script the data can be populated accordingly.
Let us represent the user table whose status field as
'status' => array(
'active' => 3,
'inactive',
'deleted',
),
In this case assume we need to create 3 users with status , active. 1 user with status inactive and 1 with deleted.
The table may be having more enum fields. So the config can expand. Depending on the configuration and fields the values will be multiples.
Consider the below example.
Eg :
$config = array(
'table1name' => array(
'field1' => array(
'active' => 3,
'inactive',
'deleted',
),
'field2' => array(
'admin',
'user',
'editor'
),
....,
'more-fields' => array(
'more-values',
)
),
'table2name' => array(
'field1' => array(
'active',
'inactive',
'deleted',
),
)
);
In this case there need to populate table1 whose field field1 with active, inactive, deleted and roles with admin, user, editor etc. ( The active, inactive etc are provided just for example. It can be just values. )
The idea is to generate more users depending on the count if any provided.
Eg :
'status' => array(
'active' => 10,
'inactive' => 2,
'deleted' => 3,
),
'roles' => array(
'admin' => 2,
'user',
'editor'
)
....,
'more-fields' => array(
'more-values',
)
So that there will be
10 * 4 => active users (10 * 2 active admin / 10 active user, 10 active editor ) +
2 * 4 => inactive users ( 2 inactive admin , 1 user, 1 editor ) +
3 * 4 => deleted users in total.
I am struggling to build the algorithm for the same.
array(
'status' => array(
'active' => 10,
'inactive' => 2,
'deleted' => 3,
),
'roles' => array(
'admin' => 2,
'user',
'editor'
),
....,
'more-fields' => array(
'more-values',
)
)
// In this example you can see we have not covered the fields of the table when they are more than 1 on save.It looks we need to build the array with values first.
foreach ($config as $table => $fields) {
foreach ($fields as $field => $values ) {
foreach ($values as $key => $statusCount) {
if (is_string($key)) {
$model = new User();
$model->$field = $key;
$model->another = 'value';
$model->save();
} else {
for ($i = 0; $i< $statusCount; $i++) {
$model = new User();
$model->$field = $key;
$model->another = 'value';
$model->save();
}
}
}
}
}
UPDATE :
Changes made according to #the-fourth-bird answer https://stackoverflow.com/a/33354032/487878
Problem is it only look for 2 fields, the fields can be 1 or n.
Are you looking for a setup like this? (Not sure what the fields for the User can be, I used 'role' and 'admin' in this example.)
$fields = array(
'status' => array(
'active' => 10,
'inactive' => 2,
'deleted' => 3,
),
'roles' => array(
'admin',
'user',
'editor'
)
);
$roles = $fields['roles'];
$statuses = $fields['status'];
foreach ($roles as $role) {
foreach ($statuses as $status => $statusCount) {
for ($i = 0; $i< $statusCount; $i++) {
$model = new User();
$model->role = $role;
$model->status = $status;
}
}
}
// Update with dynamic properties
<?php
class table1name {
public function save() {}
}
class table2name {
public function save() {}
}
$config = array(
'table1name' => array(
'field1' => array(
'active' => 3,
'inactive',
'deleted',
),
'field2' => array(
'admin',
'user' => 2,
'editor'
),
'more-fields' => array(
'more-values' => 2,
),
'color' => array(
'blue' => 2,
'red'
),
),
'table2name' => array(
'field1' => array(
'active',
'inactive',
'deleted',
),
)
);
// Adjust data structure
// If the key is a string, turn the key into values for the given multiplier in the same array.
// Then unset the key.
foreach ($config as $table => $fields) {
foreach ($fields as $field => $values ) {
foreach ($values as $key => $statusCount) {
if (is_string($key)) {
for ($i = 0; $i< $statusCount; $i++) {
$config[$table][$field][] = $key;
}
unset($config[$table][$field][(string)$key]);
}
}
}
}
$cartesians = [];
// If you want all the possible combinations for for example the 'table1name', you need a cartesian product. Used the function from this page:
//http://stackoverflow.com/questions/6311779/finding-cartesian-product-with-php-associative-arrays
function cartesian($input) {
$input = array_filter($input);
$result = array(array());
foreach ($input as $key => $values) {
$append = array();
foreach($result as $product) {
foreach($values as $item) {
$product[$key] = $item;
$append[] = $product;
}
}
$result = $append;
}
return $result;
}
// Create the cartesian products for all the keys in the $config array.
foreach ($config as $key => $tables) {
$cartesians[$key] = cartesian($tables);
}
// Loop all the objects created by the cartesian function.
foreach ($cartesians as $objectName => $cartesian) {
foreach($cartesian as $key => $value) {
$model = new $objectName();
$model->$key = $value;
$model->save();
}
}

Isolate a single column in a multi-dimensional array

Say for example you just queried a database and you recieved this 2D array.
$results = array(
array('id' => 1, 'name' => 'red' , 'spin' => 1),
array('id' => 2, 'name' => 'green', 'spin' => -1),
array('id' => 3, 'name' => 'blue' , 'spin' => .5)
);
I often find myself writing loops like this.
foreach($results as $result)
$names[] = $result['name'];
My questions is does there exist a way to get this array $names without using a loop? Using callback functions count as using a loop.
Here is a more generic example of getting every field.
foreach($results as $result)
foreach($result as $key => $value)
$fields[$key][] = $value;
As of June 20th in PHP-5.5 there is a new function array_column
For example:
$records = array(
array(
'id' => 2135,
'first_name' => 'John',
'last_name' => 'Doe'
),
array(
'id' => 3245,
'first_name' => 'Sally',
'last_name' => 'Smith'
),
array(
'id' => 5342,
'first_name' => 'Jane',
'last_name' => 'Jones'
),
array(
'id' => 5623,
'first_name' => 'Peter',
'last_name' => 'Doe'
)
);
$firstNames = array_column($records, 'first_name');
print_r($firstNames);
Will return
Array
(
[0] => John
[1] => Sally
[2] => Jane
[3] => Peter
)
There are even more examples in the above mentioned link.
I voted #Devon's response up because there really isn't a way to do what you're asking with a built-in function. The best you can do is write your own:
function array_column($array, $column)
{
$ret = array();
foreach ($array as $row) $ret[] = $row[$column];
return $ret;
}
Starting PHP 5.3, you can use this pretty call with lambda function:
$names = array_map(function ($v){ return $v['name']; }, $results);
This will return array sliced by 'name' dimension.
Simply put, no.
You will need to use a loop or a callback function like array_walk.
I did more research on this and found that ruby and prototype both have a function that does this called array_pluck,2. It's interesting that array_map has a second use that allows you to do the inverse of what i want to do here. I also found a PHP class someone is writing to emulate prototypes manipulation of arrays.
I'm going to do some more digging around and if I don't find anything else I'll work on a patch to submit to the internals#lists.php.net mailing list and see if they will add array_pluck.
For those of you that cannot upgrade to PHP5.5 right now and need this function, here is an implementation of array_column.
function array_column($array, $column){
$a2 = array();
array_map(function ($a1) use ($column, &$a2){
array_push($a2, $a1[$column]);
}, $array);
return $a2;
}
If you are running a version of PHP before 5.5 and array_column(), you can use the official replacement in plain PHP:
https://github.com/ramsey/array_column
I think this will do what you want
array_uintersect_uassoc
You would have to do something like this
$results = array(
array('id' => 1, 'name' => 'red' , 'spin' => 1),
array('id' => 2, 'name' => 'green', 'spin' => -1),
array('id' => 3, 'name' => 'blue' , 'spin' => .5)
);
$name = array_uintersect_uassoc( $results, array('name' => 'value') , 0, "cmpKey");
print_r($name);
//////////////////////////////////////////////////
// FUNCTIONS
//////////////////////////////////////////////////
function cmpKey($key1, $key2) {
if ($key1 == $key2) {
return 0;
} else {
return -1;
}
}
However, I don't have access to PHP5 so I haven't tested this.
You could do:
$tmp = array_flip($names);
$names = array_keys($tmp);
This is fast function alternative of array_column()
if(!function_exists('array_column')) {
function array_column($element_name) {
$ele = array_map(function($element) {
return $element[$element_name];
}, $a);
return $ele;
}
}
other alternative
function transpose(array $array): array
{
$out = array();
foreach ($array as $rowkey => $row) {
foreach ($row as $colkey => $col) {
$out[$colkey][$rowkey] = $col;
}
}
return $out;
}
function filter_columns(array $arr, string ...$columns): array
{
return array_intersect_key($arr, array_flip($columns));
}
test
$results = array(
array('id' => 1, 'name' => 'red' , 'spin' => 1),
array('id' => 2, 'name' => 'green', 'spin' => -1),
array('id' => 3, 'name' => 'blue' , 'spin' => .5)
);
var_dump(filter_columns(transpose($results),'name'));
var_dump(filter_columns(transpose($results),'id','name'));
var_dump(filter_columns(transpose($results),'id','spin'));

Categories