I have simple array
$a = ['a', '', 'b','c','d'];
if i json_encode it i ll have
["a","","b","c","d"]
But if i ll try to remove empty value, with array_filter or array_diff
i ll have
{"0":"a","2":"b","3":"c","4":"d"}
but i dont need array keys to be encoded, i need an encoded array without empty elements and without array keys, how to solve?
Php sandbox example: http://sandbox.onlinephpfunctions.com/code/91635a5df7fcd954dd64fe92089f2beadc81c3c4
Try this:
$a = array_values(array_filter($a));
This resets the keys of your array to be sequential. Consider how the array keys work:
$a = ['a', 'b']; // [0 => 'a', 1 => 'b']
unset($a[0]); // [1 => 'b']
$a = array_values($a); // [0 => 'b']
This resets the array keys
$a = ['a', '', 'b', 'c', 'd'];
echo json_encode(array_values(array_filter($a)));
Related
I have two arrays, $array_A and $array_B. I'd like to append the first value from $array_B to the end of the first value of $array_A and repeat this approach for all elements in both arrays.
$array_A = ['foo', 'bar', 'quuz'];
$array_B = ['baz', 'qux', 'corge'];
Expected output after squishing:
['foobaz', 'barqux', 'quuzcorge']
array_merge($array_A, $array_B) simply appends array B onto array A, and array_combine($array_A, $array_B) sets array A to be the key for array B, neither of which I want. array_map seems pretty close to what I want, but seems to always add a space between the two, which I don't want.
It would be ideal for the lengths of each array it to be irrelevant (e.g. array A has five entries, array B has seven entries, extra entries are ignored/trimmed) but not required.
// updated version
$a = ['a', 'b', 'c'];
$b = ['d', 'e', 'f', 'g'];
print_r(array_map('implode', array_map(null, $a, $b)));
Probably the fastest code, but more verbose than other options.
//updated version
$array_A = ['foo', 'bar', 'quuz'];
$array_B = ['baz', 'qux', 'corge'];
for ($i = 0, $c = count($array_A); $i<$c; $i++) {
$result[$i] = $array_A[$i].$array_B[$i];
}
var_dump($result);
There isn't an array function in PHP that does exactly that. However, you can write one yourself, like this one:
function array_zip($a1, $a2) {
$out = [];
for($i = 0; $i < min(sizeof($a1), sizeof($a2)); $i++) {
array_push($out, $a1[$i] . $a2[$i]);
}
return $out;
}
So given these arrays and running it:
$a = ["foo", "bar"];
$b = ["baz", "qux"];
print_r(array_zip($a, $b));
You would get:
Array
(
[0] => foobaz
[1] => barqux
)
Try this:
$A = ['foo', 'bar'];
$B = ['baz', 'qux'];
function arraySquish($array)
{
$new = [''];
foreach($array as $val) {
$new[0] .= $val;
}
return $new;
}
$A = arraySquish($A);
$B = arraySquish($B);
echo '<pre>';
print_r($A);
print_r($B);
echo '</pre>';
PHP Fiddle here.
An explicit array_map:
<?php
$colours = ['red', 'white', 'blue'];
$items = ['robin', 'cloud', 'mountain'];
$squished =
array_map(
function($colour, $item) {
return $colour.$item;
},
$colours,
$items
);
var_export($squished);
Output:
array (
0 => 'redrobin',
1 => 'whitecloud',
2 => 'bluemountain',
)
If you want to only go as far as the smallest array, you could either return null if either entries are null, and then filter your result.
Or truncate the arrays to the same length:
$b = array_intersect_key($b, $a);
$a = array_intersect_key($a, $b);
Regardless of if both arrays have the same length or if one is longer than the other or in what order the arrays occur in, the following technique will "squish" the values into a flat array of strings.
array_map() only needs to be called once and implode()'s default "glue" string is an empty string -- so it can be omitted.
Code: (Demo)
$a = ['a', 'b', 'c'];
$b = ['d', 'e', 'f', 'g'];
var_export(array_map(fn() => implode(func_get_args()), $a, $b));
Or consolidate the column data with spread operator: (Demo)
var_export(array_map(fn(...$column) => implode($column), $a, $b));
Output:
array (
0 => 'ad',
1 => 'be',
2 => 'cf',
3 => 'g',
)
I would like to convert a list of values such as:
$foo = ['a', 'b', 'c'];
into a list of traversing array keys such as:
$bar['a']['b']['c'] = 123;
How I can create an associative array which keys are based on a set values stored in another array?
You can make it with reference. Try this code, live demo
<?php
$foo = ['a', 'b', 'c'];
$array = [];
$current = &$array;
foreach($foo as $key) {
#$current = &$current[$key];
}
$current = 123;
print_r($array);
I would do it like this:
$foo = ['a', 'b', 'c'];
$val = '123';
foreach (array_reverse($foo) as $k => $v) {
$bar = [$v => $k ? $bar : $val];
}
We are iterating over the array in reverse and assigning the innermost value first, then building the array from the inside out.
Here is another option: Create a temporary parsable string (by extracting the first value, then appending the remaining values as square bracket wrapped strings), call parse_str(), and set the output variable as $bar.
Code: (Demo)
$foo = ['a', 'b', 'c'];
$val=123;
parse_str(array_shift($foo).'['.implode('][',$foo)."]=$val",$bar);
// built string: `a[b][c]=123`
var_export($bar);
Output:
array (
'a' =>
array (
'b' =>
array (
'c' => '123',
),
),
)
If that first method feels too hack-ish, the following recursive method is a stable approach:
Code: (Demo)
function nest_assoc($keys,$value){
return [array_shift($keys) => (empty($keys) ? $value : nest_assoc($keys,$value))];
// ^^^^^^^^^^^^^^^^^^--------------------------------------------------------extract leading key value, modify $keys
// check if any keys left-----^^^^^^^^^^^^
// no more keys, use the value---------------^^^^^^
// recurse to write the subarray contents-------------^^^^^^^^^^^^^^^^^^^^^^^^^
}
$foo=['a','b','c'];
$val=123;
var_export(nest_assoc($foo,$val));
// same output
i have two arrays in php and i am using the array_intersect function to find the common elements and if common elements exists i want to display the index of theses common elements in the 1st array
here is what i have done so far..
function check_if_exists($company_timings,$in_time)
{
$length_of_company=sizeof($company_timings);
$length_of_emp=sizeof($in_time);
$common=array_intersect($company_timings,$in_time);
$length_of_common=sizeof($common);
$key=array_search($common,$company_timings);
return $key;
}
but its not return the keys there are common elements which are 09:00:00 and 11:00:00 and when i pass 11:00:00 rather than $common in array_search then it gives the accurate result other wise with the $common_array it doesn't work,,,kindly help me in ameliorating the code
This function returns an array containing the common elements and their positions in both array, or falseif no common elements are found :
function check_if_exists($arr1, $arr2) {
$combined = array_intersect($arr1, $arr2);
if (empty($combined))
return false;
$return = array();
foreach ($combined as $elmt) {
$return[$elmt] = array();
$return[$elmt]['arr1'] = array_search($elmt, $arr1);
$return[$elmt]['arr2'] = array_search($elmt, $arr2);
}
return $return;
}
Test :
$array1 = array('a', 'b', 'c', 'd');
$array2 = array('b', 'f', 'g', 'c');
$array3 = array('n', 'o', 'p', 'e');
$exists = check_if_exists($array1, $array2);
var_dump($exists);
$exists_no = check_if_exists($array1, $array3);
var_dump($exists_no);
Output :
array (size=2)
'b' =>
array (size=2)
'arr1' => int 1
'arr2' => int 0
'c' =>
array (size=2)
'arr1' => int 2
'arr2' => int 3
boolean false
Try with array_keys function
Here is an example code. Hope it will help you.
<?php
$a = array("a","b","c");
$b = array("c","d","a");
$c = array_keys(array_intersect($a,$b));
var_dump($c);
?>
hi
i have array like $arr with 10 elements when i unset the 5 element and print the array it print he array without 5 indx. now i want to rearrange the array with 9 elements and first four values index will be same but after this values should be shifted to (previous index-1).
is there any simple method is there (array function). or i have to made a complete logic for this.
Well, if you want to maintain order, but just want to re-index the keys, you can use the array_values() function.
$a = array(
0 => 'a',
1 => 'b',
2 => 'c',
3 => 'd'
);
unset($a[1]);
$a = array(
0 => 'a',
2 => 'c',
3 => 'd'
); // Note, this is what $a is now, the re-assignment is for illustration only
$a = array_values($a);
$a = array(
0 => 'a',
1 => 'c',
2 => 'd'
); // Note, this is what $a is now, the re-assignment is for illustration only
You should use array_splice, rather than unset, to remove the elements from the array. Doing so will reorder the remaining elements:
$input = array("red", "green", "blue", "yellow");
array_splice($input, 1, 1);
// $input is now array("red", "blue", "yellow")
Not too sure if there's a better way but you can use array_reverse(), twice:
$array = array_reverse($array, false);
$array = array_reverse($array, false);
Some of the testing I will need to do will require comparing a known array with the result I am getting from the functions I will be running.
For comparing arrays recursively:
Does PHPUnit have an inbuilt function?
Does someone here have some code they have constructed to share?
Will this be something I will have to construct on my own?
Yes it does. assertEquals() and assertNotEquals() documentation.
Specifically:
assertEquals()
assertEquals(mixed $expected, mixed $actual[, string $message = ''])
Reports an error identified by $message if the two variables $expected and $actual are not equal.
assertNotEquals() is the inverse of this assertion and takes the same arguments.
Test Code:
public function testArraysEqual() {
$arr1 = array( 'hello' => 'a', 'goodbye' => 'b');
$arr2 = array( 'hello' => 'a', 'goodbye' => 'b');
$this->assertEquals($arr1, $arr2);
}
public function testArraysNotEqual() {
$arr1 = array( 'hello' => 'a', 'goodbye' => 'b');
$arr2 = array( 'hello' => 'b', 'goodbye' => 'a');
$this->assertNotEquals($arr1, $arr2);
}
[EDIT]
Here is the code for out of order aLists:
public function testArraysEqualReverse() {
$arr1 = array( 'hello' => 'a', 'goodbye' => 'b');
$arr2 = array( 'goodbye' => 'b', 'hello' => 'a');
$this->assertEquals($arr1, $arr2);
}
This test fails:
public function testArraysOutOfOrderEqual() {
$arr1 = array( 'a', 'b');
$arr2 = array( 'b', 'a');
$this->assertEquals($arr1, $arr2);
}
With message:
Failed asserting that
Array
(
[0] => b
[1] => a
)
is equal to
Array
(
[0] => a
[1] => b
)
#wilmoore
$array1 = array('hi','hi2');
$array2 = array('hi2','hi');
$this->assertEquals(array_values($array1), array_values($array2));
Will fail.
#Ben Dauphinee
It might be worth looking at assertContains(mixed $needle, array $haystack) but you would have to loop through both arrays and compare each element with the other array to ensure it contained all the required elements and no others, this however wouldn't account for an array containing two identical elements
$array1 = array('hi','hi2','hi');
$array2 = array('hi2','hi');
would pass in this case
It also doesn't account for any further recursion which would probably be quite complicated to deal with.
Depending on the complexity might just be easier in the long run to implement your own assert function.
The assertEqual method head looks like this:
public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
If the canonicalize parameter is set to true the arrays will be run through sort() first, this is usable if the keys are arbitrary and only the values matters.
However after looking over the array comparator code, the assertEqual actually does not care about the order of an associated array :) It will simply look for the expected key in the result array, and then compare the values of those keys.
I had this problem with some generated arrays with keys - I ended up passing both the expected array and the array being tested through ksort before calling assertEquals. This doesn't work on recursive arrays, though.
$expectedArray = array('foo' => 1, 'bar' => 0);
$array = array('bar' => 0, 'foo' => 1);
ksort($expectedArray);
ksort($array);
var_dump($expectedArray); // outputs array('bar' => 0, 'foo' => 1);
var_dump($array); // outputs array('bar' => 0, 'foo' => 1);
$this->assertEquals($expectedArray, $array); // passes