list of values to array chain - php

$a = Array("one", "two", "three");
$b = "text"
I have been trying to transform the above array into something like this:
$a = Array("one" => Array("two" => Array("three" => "text")));
I am looking for a way to do it without improvising but so far no luck and googleing seems to turn up with everything but what I am looking for.

Use recursion
function make(array $array, $value) {
$first = array_shift($array);
if (count($array) === 0) {
return array($first => $value);
} else {
return array($first => make($array, $value);
}
}
It takes the first item of the array and places it in $first. When placed in $first it is removed from $array. Then it checks if the array has some items left. If so it coninues the loop otherwise it end the loop.
Hope it works for you
So you can call it like:
$a = Array("one", "two", "three");
$b = "text";
$array = make($a, $b);

$i=count($array)-1;
$b=array();
$a=$array[$i];
while($i>0) {
$b=array($array[$i-1]=>$a);
$a=$b;
$i--;
}
var_dump($a);

Related

replace all keys in php array

This is my array:
['apple']['some code']
['beta']['other code']
['cat']['other code 2 ']
how can I replace all the "e" letters with "!" in the key name and keep the values
so that I will get something like that
['appl!']['some code']
['b!ta']['other code']
['cat']['other code 2 ']
I found this but because I don't have the same name for all keys I can't use It
$tags = array_map(function($tag) {
return array(
'name' => $tag['name'],
'value' => $tag['url']
);
}, $tags);
I hope your array looks like this:-
Array
(
[apple] => some code
[beta] => other code
[cat] => other code 2
)
If yes then you can do it like below:-
$next_array = array();
foreach ($array as $key=>$val){
$next_array[str_replace('e','!',$key)] = $val;
}
echo "<pre/>";print_r($next_array);
output:- https://eval.in/780144
You can stick with array_map actually. It is not really practical, but as a prove of concept, this can be done like this:
$array = array_combine(
array_map(function ($key) {
return str_replace('e', '!', $key);
}, array_keys($array)),
$array
);
We use array_keys function to extract keys and feed them to array_map. Then we use array_combine to put keys back to place.
Here is working demo.
Here we are using array_walk and through out the iteration we are replacing e to ! in key and putting the key and value in a new array.
Try this code snippet here
<?php
$firstArray = array('apple'=>'some code','beta'=>'other code','cat'=>'other code 2 ');
$result=array();
array_walk($firstArray, function($value,$key) use (&$result) {
$result[str_replace("e", "!", $key)]=$value;
});
print_r($result);
If you got this :
$firstArray = array('apple'=>'some code','beta'=>'other code','cat'=>'other code 2 ');
You can try this :
$keys = array_keys($firstArray);
$outputArray = array();
$length = count($firstArray);
for($i = 0; $i < $length; $i++)
{
$key = str_replace("e", "!", $keys[ $i ]);
$outputArray[ $key ] = $firstArray[$keys[$i]];
}
We can iterate the array and mark all problematic keys to be changed. Check for the value whether it is string and if so, make sure the replacement is done if needed. If it is an array instead of a string, then call the function recursively for the inner array. When the values are resolved, do the key replacements and remove the bad keys. In your case pass "e" for $old and "!" for $new. (untested)
function replaceKeyValue(&$arr, $old, $new) {
$itemsToRemove = array();
$itemsToAdd = array();
foreach($arr as $key => $value) {
if (strpos($key, $old) !== false) {
$itemsToRemove[]=$key;
$itemsToAdd[]=str_replace($old,$new,$key);
}
if (is_string($value)) {
if (strpos($value, $old) !== false) {
$arr[$key] = str_replace($old, $new, $value);
}
} else if (is_array($value)) {
$arr[$key] = replaceKeyValue($arr[$key], $old, $new);
}
}
for ($index = 0; $index < count($itemsToRemove); $index++) {
$arr[$itemsToAdd[$index]] = $itemsToRemove[$index];
unset($arr[$itemsToRemove[$index]]);
}
return $arr;
}
Another option using just 2 lines of code:
Given:
$array
(
[apple] => some code
[beta] => other code
[cat] => other code 2
)
Do:
$replacedKeys = str_replace('e', '!', array_keys($array));
return array_combine($replacedKeys, $array);
Explanation:
str_replace can take an array and perform the replace on each entry. So..
array_keys will pull out the keys (https://www.php.net/manual/en/function.array-keys.php)
str_replace will perform the replacements (https://www.php.net/manual/en/function.str-replace.php)
array_combine will rebuild the array using the keys from the newly updated keys with the values from the original array (https://www.php.net/manual/en/function.array-combine.php)

PHP Deep Extend Array

How can I do a deep extension of a multi dimensional associative array (for use with decoded JSON objects).
I need the php equivalent of jQuery's $.extend(true, array1, array2) with arrays instead of JSON and in PHP.
Here's an example of what I need (array_merge_recursive didn't seem to do the same thing)
$array1 = ('1'=> ('a'=>'array1a', 'b'=>'array1b'));
$array2 = ('1'=> ('a'=>'array2a', 'c'=>'array2b'));
$array3 = array_extend($array1, $array2);
//$array3 = ('1'=> ('a'=>'array2a', 'b'=>'array1b', 'c'=>'array2b'))
Notice how array2 overrides array1 if it has same value (like how extension of classes works)
If you have PHP 5.3.0+, you can use array_replace_recursive which does exactly what you need:
array_replace_recursive() replaces the values of array1 with the same
values from all the following arrays. If a key from the first array
exists in the second array, its value will be replaced by the value
from the second array. If the key exists in the second array, and not
the first, it will be created in the first array. If a key only exists
in the first array, it will be left as is. If several arrays are
passed for replacement, they will be processed in order, the later
array overwriting the previous values.
This might be what you're looking for:
function array_extend(&$result) {
if (!is_array($result)) {
$result = array();
}
$args = func_get_args();
for ($i = 1; $i < count($args); $i++) {
// we only work on array parameters:
if (!is_array($args[$i])) continue;
// extend current result:
foreach ($args[$i] as $k => $v) {
if (!isset($result[$k])) {
$result[$k] = $v;
}
else {
if (is_array($result[$k]) && is_array($v)) {
array_extend($result[$k], $v);
}
else {
$result[$k] = $v;
}
}
}
}
return $result;
}
Usage:
$arr1 = array('a' => 1, 'b' => 2, 'c' => 3);
$arr2 = array('b' => 'b', 'd' => 'd');
array_extend($arr1, $arr2);
print_r($arr1); // array('a' => 1, 'b' => 'b', 'c' => 3, 'd' => 'd')
// or, to create a new array and leave $arr1 unchanged use:
array_extend($arr3, $arr1, $arr2);
print_r($arr3); // array('a' => 1, 'b' => 'b', 'c' => 3, 'd' => 'd')
// or, use the return value:
print_r(array_extend($arr1, $arr2)); // but this will also modify $arr1
I use this in the same way I use angular.extend(dst, src) and jQuery.extend().
function extend($base = array(), $replacements = array()) {
$base = ! is_array($base) ? array() : $base;
$replacements = ! is_array($replacements) ? array() : $replacements;
return array_replace_recursive($base, $replacements);
}
Example:
si() is a utility sanitize function that grabs $_POST or $_GET and returns an array.
$s = extend(array(
'page' => 1,
'take' => 100,
'completed' => 1,
'incomplete' => 1,
), si());
Taken from array_merge docs:
function array_extend($a, $b) {
foreach($b as $k=>$v) {
if( is_array($v) ) {
if( !isset($a[$k]) ) {
$a[$k] = $v;
} else {
$a[$k] = array_extend($a[$k], $v);
}
} else {
$a[$k] = $v;
}
}
return $a;
}
You should use: https://github.com/appcia/webwork/blob/master/lib/Appcia/Webwork/Storage/Config.php#L64
/**
* Merge two arrays recursive
*
* Overwrite values with associative keys
* Append values with integer keys
*
* #param array $arr1 First array
* #param array $arr2 Second array
*
* #return array
*/
public static function merge(array $arr1, array $arr2)
{
if (empty($arr1)) {
return $arr2;
} else if (empty($arr2)) {
return $arr1;
}
foreach ($arr2 as $key => $value) {
if (is_int($key)) {
$arr1[] = $value;
} elseif (is_array($arr2[$key])) {
if (!isset($arr1[$key])) {
$arr1[$key] = array();
}
if (is_int($key)) {
$arr1[] = static::merge($arr1[$key], $value);
} else {
$arr1[$key] = static::merge($arr1[$key], $value);
}
} else {
$arr1[$key] = $value;
}
}
return $arr1;
}
With a little googling I found this:
/**
* jquery style extend, merges arrays (without errors if the passed values are not arrays)
*
* #return array $extended
**/
function extend() {
$args = func_get_args();
$extended = array();
if(is_array($args) && count($args)) {
foreach($args as $array) {
if(is_array($array)) {
$extended = array_merge($extended, $array);
}
}
}
return $extended;
}
extend($defaults, $new_options);
I guess here is the correct answer, because:
your answer have a bug with warning:
Warning: Cannot use a scalar value as an array in...
Because $a is not always an array and you use $a[$k].
array_merge_recursive does indeed merge arrays, but it converts values with duplicate keys to arrays rather than overwriting the value in the first array with the duplicate value in the second array, as array_merge does.
other aswers are not recursives or not simple.
So, here is my answer: your answer without bugs:
function array_extend(array $a, array $b) {
foreach($b as $k=>$v) {
if( is_array($v) ) {
if( !isset($a[$k]) ) {
$a[$k] = $v;
} else {
if( !is_array($a[$k]){
$a[$k]=array();
}
$a[$k] = array_extend($a[$k], $v);
}
} else {
$a[$k] = $v;
}
}
return $a;
}
And my answer with ternary operator:
function array_extend(array $a, array $b){
foreach($b as $k=>$v)
$a[$k] = is_array($v)&&isset($a[$k])?
array_extend(is_array($a[$k])?
$a[$k]:array(),$v):
$v;
return $a;
}
Edit: And a bonus one with as many arrays you want:
function array_extend(){
$args = func_get_args();
while($extended = array_shift($args))
if(is_array($extended))
break;
if(!is_array($extended))
return FALSE;
while($array = array_shift($args)){
if(is_array($array))
foreach($array as $k=>$v)
$extended[$k] = is_array($v)&&isset($extended[$k])?
array_extend(is_array($extended[$k])?
$extended[$k]:array(),$v):
$v;
}
return $extended;
}

Unsetting arrays with a specific value in a multidimensional array?

I am checking that certain elements in sub-arrays in a multidimensional array are not equal to a value and un-setting the array with that value from the multi array. I built a function so that I could easily implement this, however it doesn't appear to be working.
function multi_unset($array, $unset) {
foreach($array as $key=>$value) {
$arrayU = $array[$key];
$check = array();
for($i = 0; $i < count($unset); $i++) { // produces $array[$key][0, 2, 3]
array_push($check, $arrayU[$unset[$i]]);
}
if(in_array("-", $check)) {
unset($array[$key]);
}
}
return $array;
}
$arr = array(array("-", "test", "test", "test"), array("test", "test", "test", "test"));
$unset = array(0, 2, 3); // keys in individual arrays to check
multi_unset($arr, $unset);
print_r($arr); // Should output without $arr[0]
In this case, I'm checking if each sub-array has a "-" value in it and un-setting the array from the multi array. I am only checking specific keys in the sub-arrays (0, 2, 3) however it outputs an array without any changes. I figured I must have some scoping wrong and tried to use "global" everywhere possible, but that didn't seem to fix it.
Modified your version a bit and handled the return value.
function multi_unset($array, $unset)
{
$retVal = array();
foreach($array as $key => $value)
{
$remove = false;
foreach($unset as $checkKey)
{
if ($value[$checkKey] == "-")
$remove = true;
}
if (!$remove)
$retVal[] = $value;
}
return $retVal;
}
$arr = array(array("-", "test", "test", "test"), array("test", "test", "test", "test"));
$unset = array(0, 2, 3);
$arr = multi_unset($arr, $unset);
print_r($arr);
You may want to do some reading into Passing by Reference vs passing by value in PHP.
Heres some code that works with the given data set....
// Note the pass by reference.
function multi_unset(&$array, $unset) {
foreach($array as $pos => $subArray) {
foreach($unset as $index) {
$found = ("-" == $subArray[$index]);
if($found){
unset($subArray[$index]);
// Ver 2: remove sub array from main array; comment out previous line, and uncomment next line.
// unset($array[$pos]);
}
$array[$pos] = $subArray; // Ver 2: Comment this line out
}
}
//return $array; // No need to return since the array will be changed since we accepted a reference to it.
}
$arr = array(array("-", "test", "test", "test"), array("test", "test", "test", "test"));
$unset = array(0, 2, 3);
multi_unset($arr, $unset);
print_r($arr);

foreach with three variables add

i want to use foreach function for 3 variables
i use this code in my page:
foreach (array_combine($online_order_name, $online_order_q) as $online_order_name1 =>
$online_order_q1) {
mysql_query("insert into .......
}
how can i do that like :
<?
foreach (array_combine($online_order_name, $online_order_q,$third_variable) as
$online_order_name1 => $online_order_q1 => $third_variable2) {
?>
thank you
I guess this will solve your need:
<?php
$A=array(1,2,3);
$B=array('a','b','c');
$C=array('x','y','z');
foreach (array_map(NULL, $A, $B, $C) as $x) {
list($a, $b, $c) = $x;
echo "$a $b $c\n";
}
foreach does only the iteration over one iterator and offering one key and one value. That's how iterators are defined in PHP.
In your question you write that you need multiple values (but not keys, but I think this won't hurt). This does not work out of the box.
However, you can create an iterator that allows you to iterate over multiple iterators at once. A base class ships with PHP it's called MultipleIterator. You can then create your own ForEachMultipleArrayIterator that allows you to easily specify multiple keys and values per each iteration:
$a = array(1,2,3);
$b = array('b0' => 'a', 'b1' => 'b', 'b2' => 'c');
$c = array('c0' => 'x', 'c1' => 'y', 'c2' => 'z');
$it = new ForEachMultipleArrayIterator(
// array keyvar valuevar
array($a, 'akey' => 'avalue'),
array($b, 'bkey' => 'bvalue'),
array($c, 'ckey' => 'cvalue')
);
foreach($it as $vars)
{
extract($vars);
echo "$akey=$avalue, $bkey=$bvalue and $ckey=$cvalue \n";
}
class ForEachMultipleArrayIterator extends MultipleIterator
{
private $vars;
public function __construct()
{
parent::__construct();
$arrays = func_get_args();
foreach($arrays as $set)
{
if (count($set) != 2)
throw new invalidArgumentException('Not well defined.');
$array = array_shift($set);
if (!is_array($array))
throw new InvalidArgumentException('Not an array.');
$this->vars[key($set)] = current($set);
parent::attachIterator(new ArrayIterator($array));
}
}
public function current()
{
return array_combine(array_keys($this->vars), parent::key())
+ array_combine($this->vars, parent::current());
}
}
Demo - But if you've come that far, I'm pretty sure it's clear that what you want to do can be solved much easier by actually iterating over something else. The example above is basically the same as:
foreach(array_map(NULL, array_keys($a), $a, array_keys($b), $b, array_keys($c), $c) as $v)
{
list($akey, $avalue, $bkey, $bvalue, $ckey, $cvalue) = $v;
echo "$akey=$avalue, $bkey=$bvalue and $ckey=$cvalue \n";
}
So better get your arrays into the right order and then process them :)
See also: Multiple index variables in PHP foreach loop.
I don't believe this is possible with array_combine and foreach, because they operate specifically on key/value pairs in an associative array. PHP doesn't have tuples as a builtin data structure.
for ($i = 0, $length = count($array1); $i < $length; $i++) {
list($a, $b, $c) = array($array1[$i], $array2[$i], $array3[$i]);
...
}
You should think about a better array structure though that doesn't require you to pull information from three different arrays. Something like:
$orders = array(
array('name' => 'Foo', 'q' => 'bar', 'third' => 'Baz'),
...
);

How to get random value out of an array?

I have an array called $ran = array(1,2,3,4);
I need to get a random value out of this array and store it in a variable, how can I do this?
You can also do just:
$k = array_rand($array);
$v = $array[$k];
This is the way to do it when you have an associative array.
PHP provides a function just for that: array_rand()
http://php.net/manual/en/function.array-rand.php
$ran = array(1,2,3,4);
$randomElement = $ran[array_rand($ran, 1)];
$value = $array[array_rand($array)];
You can use mt_rand()
$random = $ran[mt_rand(0, count($ran) - 1)];
This comes in handy as a function as well if you need the value
function random_value($array, $default=null)
{
$k = mt_rand(0, count($array) - 1);
return isset($array[$k])? $array[$k]: $default;
}
You could use the array_rand function to select a random key from your array like below.
$array = array("one", "two", "three", "four", "five", "six");
echo $array[array_rand($array, 1)];
or you could use the rand and count functions to select a random index.
$array = array("one", "two", "three", "four", "five", "six");
echo $array[rand(0, count($array) - 1)];
Derived from Laravel Collection::random():
function array_random($array, $amount = 1)
{
$keys = array_rand($array, $amount);
if ($amount == 1) {
return $array[$keys];
}
$results = [];
foreach ($keys as $key) {
$results[] = $array[$key];
}
return $results;
}
Usage:
$items = ['foo', 'bar', 'baz', 'lorem'=>'ipsum'];
array_random($items); // 'bar'
array_random($items, 2); // ['foo', 'ipsum']
A few notes:
$amount has to be less than or equal to count($array).
array_rand() doesn't shuffle keys (since PHP 5.2.10, see 48224), so your picked items will always be in original order. Use shuffle() afterwards if needed.
Documentation: array_rand(), shuffle()
edit: The Laravel function has noticeably grown since then, see Laravel 5.4's Arr::random(). Here is something more elaborate, derived from the grown-up Laravel function:
function array_random($array, $number = null)
{
$requested = ($number === null) ? 1 : $number;
$count = count($array);
if ($requested > $count) {
throw new \RangeException(
"You requested {$requested} items, but there are only {$count} items available."
);
}
if ($number === null) {
return $array[array_rand($array)];
}
if ((int) $number === 0) {
return [];
}
$keys = (array) array_rand($array, $number);
$results = [];
foreach ($keys as $key) {
$results[] = $array[$key];
}
return $results;
}
A few highlights:
Throw exception if there are not enough items available
array_random($array, 1) returns an array of one item (#19826)
Support value "0" for the number of items (#20439)
The array_rand function seems to have an uneven distribution on large arrays, not every array item is equally likely to get picked. Using shuffle on the array and then taking the first element doesn't have this problem:
$myArray = array(1, 2, 3, 4, 5);
// Random shuffle
shuffle($myArray);
// First element is random now
$randomValue = $myArray[0];
Another approach through flipping array to get direct value.
Snippet
$array = [ 'Name1' => 'John', 'Name2' => 'Jane', 'Name3' => 'Jonny' ];
$val = array_rand(array_flip($array));
array_rand return key not value. So, we're flipping value as key.
Note:
PHP key alway be an unique key, so when array is flipped, duplicate value as a key will be overwritten.
$rand = rand(1,4);
or, for arrays specifically:
$array = array('a value', 'another value', 'just some value', 'not some value');
$rand = $array[ rand(0, count($array)-1) ];
On-liner:
echo $array[array_rand($array,1)]
In my case, I have to get 2 values what are objects. I share this simple solution.
$ran = array("a","b","c","d");
$ranval = array_map(function($i) use($ran){return $ran[$i];},array_rand($ran,2));
One line: $ran[rand(0, count($ran) - 1)]
I needed one line version for short array:
($array = [1, 2, 3, 4])[mt_rand(0, count($array) - 1)]
or if array is fixed:
[1, 2, 3, 4][mt_rand(0, 3]
Does your selection have any security implications? If so, use random_int() and array_keys(). (random_bytes() is PHP 7 only, but there is a polyfill for PHP 5).
function random_index(array $source)
{
$max = count($source) - 1;
$r = random_int(0, $max);
$k = array_keys($source);
return $k[$r];
}
Usage:
$array = [
'apple' => 1234,
'boy' => 2345,
'cat' => 3456,
'dog' => 4567,
'echo' => 5678,
'fortune' => 6789
];
$i = random_index($array);
var_dump([$i, $array[$i]]);
Demo: https://3v4l.org/1joB1
Use rand() to get random number to echo random key. In ex: 0 - 3
$ran = array(1,2,3,4);
echo $ran[rand(0,3)];
This will work nicely with in-line arrays. Plus, I think things are tidier and more reusable when wrapped up in a function.
function array_rand_value($a) {
return $a[array_rand($a)];
}
Usage:
array_rand_value(array("a", "b", "c", "d"));
On PHP < 7.1.0, array_rand() uses rand(), so you wouldn't want to this function for anything related to security or cryptography. On PHP 7.1.0+, use this function without concern since rand() has been aliased to mt_rand().
I'm basing my answer off of #ÓlafurWaage's function. I tried to use it but was running into reference issues when I had tried to modify the return object. I updated his function to pass and return by reference. The new function is:
function &random_value(&$array, $default=null)
{
$k = mt_rand(0, count($array) - 1);
if (isset($array[$k])) {
return $array[$k];
} else {
return $default;
}
}
For more context, see my question over at Passing/Returning references to object + changing object is not working
Get random values from an array.
function random($array)
{
/// Determine array is associative or not
$keys = array_keys($array);
$givenArrIsAssoc = array_keys($keys) !== $keys;
/// if array is not associative then return random element
if(!$givenArrIsAssoc){
return $array[array_rand($array)];
}
/// If array is associative then
$keys = array_rand($array, $number);
$results = [];
foreach ((array) $keys as $key) {
$results[] = $array[$key];
}
return $results;
}
mt_srand usage example
if one needs to pick a random row from a text but same all the time based on something
$rows = array_map('trim', explode("\n", $text));
mt_srand($item_id);
$row = $rows[rand(0, count($rows ) - 1)];
A simple way to getting Randdom value form Array.
$color_array =["red","green","blue","light_orange"];
$color_array[rand(0,3)
now every time you will get different colors from Array.
You get a random number out of an array as follows:
$randomValue = $rand[array_rand($rand,1)];

Categories