I was wondering is it possible to convert the following array:
Array (
"2016-03-03 19:17:59",
"2016-03-03 19:20:54",
"2016-05-03 19:12:37"
)
Into this:
Array (
"2016-03-03",
"2016-03-03",
"2016-05-03"
)
Without creating any loops?
There's no explicit loops, if you can use array_map, although internally it loops:
function format_date($val) {
$v = explode(" ", $val);
return $v[0];
}
$arr = array_map("format_date", $arr);
From the PHP Manual:
array_map() returns an array containing all the elements of array1 after applying the callback function to each one. The number of parameters that the callback function accepts should match the number of arrays passed to the array_map().
Also, when you are dealing with Dates, the right way to do is as follows:
return date("Y-m-d", strtotime($val));
The simple way, using loops is to use a foreach():
foreach($arr as $key => $date)
$arr[$key] = date("Y-m-d", strtotime($date));
This is the most simplest looping way I can think of considering the index to be anything.
Input:
<?php
$arr = array(
"2016-03-03 19:17:59",
"2016-03-03 19:20:54",
"2016-05-03 19:12:37"
);
function format_date($val) {
$v = explode(" ", $val);
return $v[0];
}
$arr = array_map("format_date", $arr);
print_r($arr);
Output
Array
(
[0] => 2016-03-03
[1] => 2016-03-03
[2] => 2016-05-03
)
Demo: http://ideone.com/r9AyYV
Yes, use map:
function first10($s) {
return substr($s, 0, 10);
}
$result = array_map("first10", $yourArray);
WARNING: this is a good solution only if you are sure that the date format does not change, in other words the first 10 characters must contain the date.
Praveen Kumar's answer is probably the better solution but there is a way to do with what wouldn't really been seen as a loop. instead you use recursion
function explodeNoLoop($array,$delim,$index=0)
{
$returnArr = array();
if(isset($array[$index]))
{
$expldoed = explode($delim,$array[$index]);
array_push($returnArr,$expldoed[0]);
}
if(isset($array[$index+1]))
{
$returnArr = array_merge($returnArr,explodeNoLoop($array,$delim,$index+1));
}
return $returnArr;
}
$myArr = array (
"2016-03-03 19:17:59",
"2016-03-03 19:20:54",
"2016-05-03 19:12:37"
);
var_dump(explodeNoLoop($myArr," "));
example
How this code works is that with the function we explode the array at the index provided by the function parameter and add this to our returning array. Then we check if there is a value set at the next index which is +1 of the index we passed into the function. If it exists then we call the function again with the new index with the same array and delimiter. We then merge the results of this with our returner array and then return that.
However, with this one should be careful of nest level errors where you excursively call a function too many times, like looking into the reflection of a mirror in a mirror.
Related
I need to remove values from an array that occur more than one time in the array.
For example:
$value = array(10,10,5,8);
I need this result:
$value = array(5,8);
Is there any in-built function in php?
I tried this, but this will not return my expected result:
$unique = array_unique($value);
$dupes = array_diff_key($value, $unique);
You can use array functions and ditch the foreach loops if you wish:
Here is a one-liner:
Code:
$value = [10, 10, 5, 8];
var_export(array_keys(array_intersect(array_count_values($value),[1])));
As multi-line:
var_export(
array_keys(
array_intersect(
array_count_values($value),
[1]
)
)
);
Output:
array (
0 => 5,
1 => 8,
)
This gets the value counts as an array, then uses array_intersect() to only retain values that occur once, then turns the keys into the values of a zero-index array.
The above snippet works identically to #modsfabio's and #axiac's answers. The ONLY advantage in my snippet is brevity. It is possible that their solutions may outperform mine, but judging speed on relatively small data sets may be a waste of dev time. For anyone processing relatively large data sets, do your own benchmarking to find the technique that works best.
For lowest computational/time complexity, use a single loop and as you iterate conditionally populate a lookup array and unset() as needed.
Code: (Demo) (Crosslink to my CodeReview answer)
$values = [10, 10, 5, 8];
$found = [];
foreach ($values as $index => $value) {
if (!isset($found[$value])) {
$found[$value] = $index;
} else {
unset($values[$index], $values[$found[$value]]);
}
}
var_export($values);
// [2 => 5, 3 => 8]
A couple of notes:
If processing float values, using a technique that stores the values as keys (as all of my snippets do), then the results may be incorrect because php will change floats to integers when used as keys.
PHP is consistently much faster at searching for keys than it is at searching for values.
You can do it like this using array_count_values() and a foreach loop:
<?php
$input = array(10,10,5,8);
$output = array();
foreach(array_count_values($input) as $value => $count)
{
if($count == 1)
{
$output[] = $value;
}
}
var_dump($output);
Output:
array(2) {
[0]=>
int(5)
[1]=>
int(8)
}
Example: https://eval.in/819461
A possible approach:
$value = array(10,10,5,8);
$output = array_keys(
array_filter(
array_count_values($value),
function ($count) {
return $count == 1;
}
)
)
array_count_values() produces an array that associates to each unique value from $value the number of times it appears in the array.
array_filter() keeps in this result only the entries (the keys) that appear only once in the original array.
array_keys() produces the desired result.
I would use array_count_values to get an array with how often every element occurs in the array. Then remove all the elements from the original array that occur more than once.
You need to use array_count_values(), array_search() and unset() functions.
<?php
$value = array(10,10,5,8);
echo '<pre>';print_r($value);echo '</pre>';
$cnt = array_count_values($value);
$dup = array();
foreach ($cnt as $k => $repeated) {
if ($repeated > 1) {
if(($key = array_search($k, $value)) !== false) {
unset($value[$key]);
}
}
}
echo '<pre>';print_r($cnt);echo '</pre>';
echo '<pre>';print_r($value);echo '</pre>';
?>
Demo
you can use
foreach loop
and
array_diff() function:
$value=array(10,10,5,8);
$duplicated=array();
foreach($value as $k=>$v)
{
if($kt=array_search($v,$value))!==false and
$k!=$kt)
{if (count(array_keys($array, $value)) > 1)
{
/* Execute code */
}
unset($value[$kt];$duplicated[]=$v;
}
}
$result=array_diff($values,$duplicated);
print_r($result);
output
Array([2]=>5[3]=>8)
How can I delete duplicates in array?
For example if I had the following array:
$array = array('1','1','2','3');
I want it to become
$array = array('2','3');
so I want it to delete the whole value if two of it are found
Depending on PHP version, this should work in all versions of PHP >= 4.0.6 as it doesn't require anonymous functions that require PHP >= 5.3:
function moreThanOne($val) {
return $val < 2;
}
$a1 = array('1','1','2','3');
print_r(array_keys(array_filter(array_count_values($a1), 'moreThanOne')));
DEMO (Change the PHP version in the drop-down to select the version of PHP you are using)
This works because:
array_count_values will go through the array and create an index for each value and increment it each time it encounters it again.
array_filter will take the created array and pass it through the moreThanOne function defined earlier, if it returns false, the key/value pair will be removed.
array_keys will discard the value portion of the array creating an array with the values being the keys that were defined. This final step gives you a result that removes all values that existed more than once within the original array.
You can filter them out using array_count_values():
$array = array('1','1','2','3');
$res = array_keys(array_filter(array_count_values($array), function($freq) {
return $freq == 1;
}));
The function returns an array comprising the original values and their respective frequencies; you then pick only the single frequencies. The end result is obtained by retrieving the keys.
Demo
Try this code,
<?php
$array = array('1','1','2','3');
foreach($array as $data){
$key= array_keys($array,$data);
if(count($key)>1){
foreach($key as $key2 => $data2){
unset($array[$key2]);
}
}
}
$array=array_values($array);
print_r($array);
?>
Output
Array ( [0] => 2 [1] => 3 )
PHP offers so many array functions, you just have to combine them:
$arr = array_keys(array_filter(array_count_values($arr), function($val) {
return $val === 1;
}));
Reference: array_keys, array_filter, array_count_values
DEMO
Remove duplicate values from an array.
array_unique($array)
$array = array(4, "4", "3", 4, 3, "3");
$result = array_unique($array);
print_r($result);
/*
Array
(
[0] => 4
[2] => 3
)
*/
I'm currently using array_map to apply callbacks to elements of an array. But I want to be able to pass an argument to the callback function like array_walk does.
I suppose I could just use array_walk, but I need the return value to be an array like if you use array_map, not TRUE or FALSE.
So is it possible to use array_map and pass an argument to the callback function? Or perhaps make the array_walk return an array instead of boolean?
You don't need it to return an array.
Instead of:
$newArray = array_function_you_are_looking_for($oldArray, $funcName);
It's:
$newArray = $oldArray;
array_walk($newArray, $funcName);
If you want return value is an array, just use array_map. To add additional parameters to array_map use "use", ex:
array_map(function($v) use ($tmp) { return $v * $tmp; }, $array);
or
array_map(function($v) use ($a, $b) { return $a * $b; }, $array);
Depending on what kind of arguments you need to pass, you could create a wrapped function:
$arr = array(2, 4, 6, 8);
function mapper($val, $constant) {
return $val * $constant;
}
$constant = 3;
function wrapper($val) {
return mapper($val, $GLOBALS['constant']);
}
$arr = array_map('wrapper', $arr);
This actually seems too simple to be true. I suspect we'll need more context to really be able to help.
To expand a bit on Hieu's great answer, you can also use the $key => $value pairs of the original array. Here's an example with some code borrowed from comment section http://php.net/manual/en/function.array-map.php
The following will use 'use' and include an additional parameter which is a new array.
Below code will grab "b_value" and "d_value" and put into a new array $new_arr
(useless example to show a point)
// original array
$arr = ("a" => "b_value",
"c" => "d_value");
// new array
$new_arr = array();
array_map(function($k,$v) use (&$new_arr) { $new_arr[] = $v;}, array_keys($arr), $arr);
^ $k is key and $v is value
print_r of $new_arr is
Array
(
[0] => b_value
[1] => d_value
)
Each item in my array is an array of about 5 values.. Some of them are numerical ending in "GB".. I need the same array but with "GB" stripped out so that just the number remains.
So I need to iterate through my whole array, on each subarray take each value and strip the string "GB" from it and create a new array from the output.
Can anyone recommend and efficient method of doing this?
You can use array_walk_recursive() for this:
array_walk_recursive($arr, 'strip_text', 'GB');
function strip_text(&$value, $key, $string) {
$value = str_replace($string, '', $value);
}
It's a lot less awkward than traversing an array with its values by reference (correctly).
You can create your own custom function to iterate through an array's value's, check if the substring GB exists, and if so, remove it. With that function you can pass the original array and the function into array_map
// i only did the subarray part
$diskSizes = array("500", "300 GB", "200", "120 GB", "130GB");
$newArray = array();
foreach ($diskSizes as $diskSize) {
$newArray[] = str_replace('GB', '', $diskSize);
}
// look at the new array
print_r($newArray);
$arr = ...
foreach( $arr as $k => $inner ) {
foreach( $inner as $kk => &$vv ) {
$vv = str_replace( 'GB', '', $vv );
}
}
This actually keeps the original arrays intact with the new strings. (notice &$vv, which means that i'm getting the variable by reference, which means that any changes to $vv within the loop will affect the actual string, not by copying)
Do I really have to do this to reset an array?
foreach ($array as $i => $value) {
unset($array[$i]);
}
EDIT:
This one makes more sense, as the previous one is equivalent to $array=array();
foreach ($array as $i => $value) {
$array[$i]=NULL;
}
$keys = array_keys($array);
$values = array_fill(0, count($keys), null);
$new_array = array_combine($keys, $values);
Get the Keys
Get an array of nulls with the same number of elements
Combine them, using keys and the keys, and the nulls as the values
As comments suggest, this is easy as of PHP 5.2 with array_fill_keys
$new_array = array_fill_keys(array_keys($array), null);
Fill array with old keys and null values
$array = array_fill_keys(array_keys($array), null)
There is no build-in function to reset an array to just it's keys.
An alternative would be via a callback and array_map():
$array = array( 'a' => 'foo', 'b' => 'bar', 'c' => 'baz' );
With regular callback function
function nullify() {}
$array = array_map('nullify', $array);
Or with a lambda with PHP < 5.3
$array = array_map(create_function('', ''), $array);
Or with lambda as of PHP 5.3
$array = array_map(function() {}, $array);
In all cases var_dump($array); outputs:
array(3) {
["a"]=> NULL
["b"]=> NULL
["c"]=> NULL
}
Define this function and call it whenever you need it:
function erase_val(&$myarr) {
$myarr = array_map(create_function('$n', 'return null;'), $myarr);
}
// It's call by reference so you don't need to assign your array to a variable.
// Just call the function upon it
erase_val($array);
That's all!
Get the array keys, then use them to create a new array with NULL values:
array_fill_keys(array_keys($array), NULL);
About array_fill_keys():
The array_fill_keys() function fills an array with values, specifying keys.
About array_keys():
The array_keys() function returns all the keys of an array.
foreach($a as &$v)
$v = null;
The reasoning behind setting an array item to null is that an array needs to have a value for each key, otherwise a key makes no sense. That is why it is called a key - it is used to access a value. A null value seems like a reasonable choice here.
Wrap it in a [reusable] procedure:
function array_purge_values(&$a) {
foreach($a as &$v)
$v = null;
}
Keep in mind though that PHP versions 5.3 and those released later, pass values to functions by reference by default, i.e. the ampersand preceding argument variable in the function declaration is redundant. Not only that, but you will get a warning that the notion is deprecated.
If you need to nullify the values of a associative array you can walk the whole array and make a callback to set values to null thus still having keys
array_walk($ar,function(&$item){$item = null;});
In case if you need to nullify the whole array just reassign it to empty one
$ar = array();
unset would delete the key, You need to set the value to null or 0 as per your requirement.
Example
I don't get the question quite well, but your example
foreach ($array as $i => $value) {
unset($array[$i]);
}
is equivilent to
$array = array();
Why not making an array with required keys and asinging it to variable when you want reset it?
function resetMyArr(&$arr)
{
$arr = array('key1'=>null,'key2'=>null);
}
This is a fairly old topic, but since I referenced to it before coming up with my own solution for a more specific result, so therefore I will share with you that solution.
The desired result was to nullify all values, while keeping keys, and for it to recursively search the array for sub-arrays as well.
RECURSIVELY SET MULTI-LEVEL ARRAY VALUES TO NULL:
function nullifyArray(&$arrayData) {
if (is_array($arrayData)) {
foreach ($arrayData as $aKey => &$aValue) {
if (is_array($aValue)) {
nullifyArray($aValue);
} else {
$aValue = null;
}
}
return true; // $arrayData IS an array, and has been processed.
} else {
return false; // $arrayData is NOT an array, no action(s) were performed.
}
}
And here is it in use, along with BEFORE and AFTER output of the array contents.
PHP code to create a multilevel-array, and call the nullifyArray() function:
// Create a multi-level array.
$testArray = array(
'rootKey1' => 'rootValue1',
'rootKey2' => 'rootValue2',
'rootArray1' => array(
'subKey1' => 'subValue1',
'subArray1' => array(
'subSubKey1' => 'subSubValue1',
'subSubKey2' => 'subSubValue2'
)
)
);
// Nullify the values.
nullifyArray($testArray);
BEFORE CALL TO nullifyArray():
Array
(
[rootKey1] => rootValue1
[rootKey2] => rootValue2
[rootArray1] => Array
(
[subKey1] => subValue1
[subArray1] => Array
(
[subSubKey1] => subSubValue1
[subSubKey2] => subSubValue2
)
)
)
AFTER CALL TO nullifyArray():
Array
(
[rootKey1] =>
[rootKey2] =>
[rootArray1] => Array
(
[subKey1] =>
[subArray1] => Array
(
[subSubKey1] =>
[subSubKey2] =>
)
)
)
I hope it helps someone/anyone, and Thank You to all who previously answered the question.
And speed test
This test shows speed when clearing a large array
$a1 = array();
for($i=0;$i<=1000;$i++)
{
$a1['a'.$i] = $i;
}
$b = $a1;
$start_time = microtime(TRUE);
foreach ($a1 as $field => $val) {
$a1[$field]=NULL;
}
$end_time = microtime(TRUE);
$duration = $end_time - $start_time;
var_dump( $duration*1000 );
var_dump('all emelent of array is '.reset($a1));
$start_time = microtime(TRUE);
$allkeys = array_keys($b);
$newarray = array_fill_keys($allkeys, null);
$end_time = microtime(TRUE);
$duration = $end_time - $start_time;
var_dump( $duration*1000 );
var_dump('all emelent of array is '.reset($newarray));
Just do this:
$arrayWithKeysOnly = array_keys($array);
http://php.net/manual/en/function.array-keys.php
EDIT: Addressing comment:
Ok, then do this:
$arrayWithKeysProper = array_flip(array_keys($array));
http://www.php.net/manual/en/function.array-flip.php
EDIT: Actually thinking about it, that probably won't work either.