Related
Here is an example array. The value formatting is HH:MM:SS
$array = ['17:31:05', '17:31:06', '17:31:07' ...etc...];
What I need to do is remove the seconds and the colon before from all values within the $array. My attempt was to do the following, but it did not work.
foreach($array as $key => $val){
$val = substr($val, 0, -3);
}
Any suggestions?
In your questions example code you modify $val and not the $array.
Instead modify the $array:
foreach($array as $key => $val){
$array[$key] = substr($val, 0, -3);
}
or
foreach($array as &$val){
$val = substr($val, 0, -3);
}
unset($val); # remove the reference on $val - recommended child protection
I recommend the first one since reference variables are somewhat error-prone (harder to understand).
Your code is not too far off, you just put it in the wrong manner onto the array. Look the following different example:
$removeSeconds = function($val) {
return substr($val, 0, -3);
}
$arrayWithoutSeconds = array_map($removeSeconds, $array);
The (anonymous) function contains basically your code and then it uses the array_map function to map that function on to the array.
If you prefer to use foreach this is possible as well, however if you want to write into $val in your case, it must be a reference to the value inside the array and this is not always straight forward.
For an array (that is not a reference and not containing any references as "values"), it works as the following:
foreach ($array as &$val) {
### ^-- iterate over a reference (PHP variable alias)
$val = substr($val, 0, -3);
}
unset ($val); ### remove the reference (it does not unset the last array element!)
Even the unset operation after the foreach is technically not necessary, it's recommended so that you can not set $val later on in your code (and then changing the last value of the array).
This is why it is most often more simple to iterate over keys and values, then writing to the specific element directly:
foreach ($array as $key => $val) {
$array[$key] = substr($val, 0, -3);
}
As you can see for all these different cases you could have used the (anonymous) function as on top, therefore using it in the first place would have spared you to change most code. You also have a common mapping situation here, so I think it's most applicable. However this can differ, so keep your mind open and use what you deem fit best in your concrete situation.
You cant use foreach loop for that like this. Use for loop instead
for ($i = 0; $i < count($array); $i++)
{
$array[$i] = substr($array[$i], 0, -3);
}
That's because in a foreach the value of the current element is copied over to the $val variable.
Set $array[$key] with the value you want, and it'll work.
Simple and short solution:
$array = array_map(function($time) {
return substr($time, 0, -3);
}, $array);
This shoud work fine
$result = preg_replace('/(?<=:\d\d):\d+/', '', $array);
or if you need an additional actions inside your loop, do
foreach($array as $key => $val){
$array[$key] = substr($val, 0, -3);
}
I have the following fairly simple code, where I need to determine if a certain value exists in an array:
$testvalue = $_GET['testvalue']; // 4
$list = '3, 4, 5';
$array = array($list);
if (in_array($testvalue, $array)) { // Code if found } else { // Code if not found }
Even though it is obvious that the number 4 is in the array, the code returns the code inside the else bracets. What have I done wrong?
Change the third line:
$array = array_map('trim', explode(',',$list));
$array here is:
$array = array('3, 4, 5');
which is not the same as:
$array = array(3, 4, 5);
So, fix the way you are creating this array.. don't do it from a string.
Your array contains just one value, the string 3, 4, 5.
See the example on CodePad.
If you want to convert your string in an array, you can use:
$array = explode(', ', $list);
I have added a space behind the comma, but a safer method would be to use just a comma and then trim all values.
Lets say I have an array as follows :
$sampArray = array (1,4,2,1,6,4,9,7,2,9)
I want to remove all the duplicates from this array, so the result should be as follows:
$resultArray = array(1,4,2,6,9,7)
But here is the catch!!! I don't want to use any PHP in built functions like array_unique().
How would you do it ? :)
Here is a simple O(n)-time solution:
$uniqueme = array();
foreach ($array as $key => $value) {
$uniqueme[$value] = $key;
}
$final = array();
foreach ($uniqueme as $key => $value) {
$final[] = $key;
}
You cannot have duplicate keys, and this will retain the order.
A serious (working) answer:
$inputArray = array(1, 4, 2, 1, 6, 4, 9, 7, 2, 9);
$outputArray = array();
foreach($inputArray as $inputArrayItem) {
foreach($outputArray as $outputArrayItem) {
if($inputArrayItem == $outputArrayItem) {
continue 2;
}
}
$outputArray[] = $inputArrayItem;
}
print_r($outputArray);
This depends on the operations you have available.
If all you have to detect duplicates is a function that takes two elements and tells if they are equal (one example will be the == operation in PHP), then you must compare every new element with all the non-duplicates you have found before. The solution will be quadratic, in the worst case (there are no duplicates), you need to do (1/2)(n*(n+1)) comparisons.
If your arrays can have any kind of value, this is more or less the only solution available (see below).
If you have a total order for your values, you can sort the array (n*log(n)) and then eliminate consecutive duplicates (linear). Note that you cannot use the <, >, etc. operators from PHP, they do not introduce a total order. Unfortunately, array_unique does this, and it can fail because of that.
If you have a hash function that you can apply to your values, than you can do it in average linear time with a hash table (which is the data structure behind an array). See
tandu's answer.
Edit2: The versions below use a hashmap to determine if a value already exists. In case this is not possible, here is another variant that safely works with all PHP values and does a strict comparison (Demo):
$array = array (1,4,2,1,6,4,9,7,2,9);
$unique = function($a)
{
$u = array();
foreach($a as $v)
{
foreach($u as $vu)
if ($vu===$v) continue 2
;
$u[] = $v;
}
return $u;
};
var_dump($unique($array)); # array(1,4,2,6,9,7)
Edit: Same version as below, but w/o build in functions, only language constructs (Demo):
$array = array (1,4,2,1,6,4,9,7,2,9);
$unique = array();
foreach($array as $v)
isset($k[$v]) || ($k[$v]=1) && $unique[] = $v;
var_dump($unique); # array(1,4,2,6,9,7)
And in case you don't want to have the temporary arrays spread around, here is a variant with an anonymous function:
$array = array (1,4,2,1,6,4,9,7,2,9);
$unique = function($a) /* similar as above but more expressive ... ... you have been warned: */ {for($v=reset($a);$v&&(isset($k[$v])||($k[$v]=1)&&$u[]=$v);$v=next($a));return$u;};
var_dump($unique($array)); # array(1,4,2,6,9,7)
First was reading that you don't want to use array_unique or similar functions (array_intersect etc.), so this was just a start, maybe it's still of som use:
You can use array_flip PHP Manual in combination with array_keys PHP Manual for your array of integers (Demo):
$array = array (1,4,2,1,6,4,9,7,2,9);
$array = array_keys(array_flip($array));
var_dump($array); # array(1,4,2,6,9,7)
As keys can only exist once in a PHP array and array_flip retains the order, you will get your result. As those are build in functions it's pretty fast and there is not much to iterate over to get the job done.
<?php
$inputArray = array(1, 4, 2, 1, 6, 4, 9, 7, 2, 9);
$outputArray = array();
foreach ($inputArray as $val){
if(!in_array($val,$outputArray)){
$outputArray[] = $val;
}
}
print_r($outputArray);
You could use an intermediate array into which you add each item in turn. prior to adding the item you could check if it already exists by looping through the new array.
What is the fastest way to convert a simple array to an associative array in PHP so that values can be checked in the isset($array[$value])?
I.e. fastest way to do the following conversion:
$array = array(1, 2, 3, 4, 5);
$assoc = array();
foreach ($array as $i => $value) {
$assoc[$value] = 1;
}
Your code is the exact equivalent of:
$assoc = array_fill_keys(array(1, 2, 3, 4, 5), 1); // or
$assoc = array_fill_keys(range(1, 5), 1);
array_flip(), while it may work for your purpose, it's not the same.
PHP ref: array_fill_keys(), array_flip()
If anyone is still wondering how to do this, there is an easier solution for this by using the array_combine function.
$array = array(1, 2, 3, 4, 5);
$assoc = array_combine($array,$array);
array_flip() is exactly doing that:
array_flip() returns an array in flip order, i.e. keys from trans become values and values from trans become keys.
Note that the values of trans need to be valid keys, i.e. they need to be either integer or string. A warning will be emitted if a value has the wrong type, and the key/value pair in question will not be flipped.
If a value has several occurrences, the latest key will be used as its values, and all others will be lost.
But apart from that, there is only one type of array in PHP. Even numerical ("simple", as you call it) arrays are associative.
Simply use this logic
$var1 = json_encode($arr1, JSON_FORCE_OBJECT);
$var1 = json_decode($var1);
where $arr1 is the array that has to be converted to associative array.
This can be achieved by json_encode and the json_decode the same
function simple_to_associative($array) {
$new_array = [];
$i = 0;
$last_elem = end($array);
$nr_elems = count($array);
foreach ($array as $index=>$value) {
if($i % 2 == 0 && $last_elem == $value) {
$new_array[$value] = '';
} elseif($i % 2 == 0) {
$new_array[$value] = $array[$index + 1];
}
$i++;
}
return $new_array;
}
Would work on any simple array of unlimited elements.
I have an array:
$arr = array('foo', 'bar', 'bash', 'monkey', 'badger');
I want to have the elements in that array appear as the variables in my list():
list($foo, $bar, $bash, $monkey, $badger) = $data;
Without actually specifying the variables, I tried;
list(implode(",$", $arr)) = $data; and
list(extract($arr)) = $data;
But they don't work, I get:
Fatal error: Can't use function return value in write context
Does anyone have any idea whether this is possible?
UPDATE: more context:
I am getting a CSV of data from an API, the first row is column names, each subsequent row is data. I want to build an associative array that looks like this:
$data[0]['colname1'] = 'col1data';
$data[0]['colname2'] = 'col2data';
$data[0]['colname3'] = 'col3data';
$data[1]['colname1'] = 'col1data';
$data[1]['colname2'] = 'col2data';
$data[1]['colname3'] = 'col3data';
Before I do that, however, I want to make sure I have all the columns I need. So, I build an array with the column names I require, run some checks to ensure the CSV does contain all the columns I need. Once thats done, the code looks somewhat like this (which is executed on a foreach() for each row of data in the CSV):
//$data is an array of data WITHOUT string indexes
list( $col1,
$col2,
$col3,
...
$col14
) = $data;
foreach($colNames AS $name)
{
$newData[$i][$name] = $$name;
}
// Increemnt
$i++;
As I already HAVE an array of column name, I though it would save some time to use THAT in the list function, instead of explicitly putting in each variable name.
The data is cleaned and sanitised elsewhere.
Cheers,
Mike
I want to have the elements in that array appear as the variables in my list():
i think there is your problem in understanding. list() does not create a new list structure or variable, it can only be used to assign many variables at once:
$arr = array(1, 2, 3);
list($first, $second, $third) = $arr;
// $first = 1, $second = 2, $third = 3
see http://php.net/list for more information.
you are probably looking for an associative array. you can create it with the following code:
$arr = array('first' => 1, 'second' => 2, 'third' => 3);
// $arr['first'] = 1, …
If some rows in your input file are missing columns, you can't really know which one is missing. Counting the number of values and aborting or jumping to next row when less than expected should be enough.
... unless you set the rule that last columns are optional. I'll elaborate on this.
Your code sample is far for complete but it seems that your problem is that you are using arrays everywhere except when matching column names to cell values. Use arrays as well: you don't need individual variables and they only make it harder. This is one of the possible approaches, not necessarily the best one but (I hope) clear enough:
<?php
$required_columns = array('name', 'age', 'height');
$input_data = array(
array('John', 33, 169),
array('Bill', 40, 180),
array('Ashley', 21, 155),
array('Vincent', 13), // Incomplete record
array('Michael', 55, 182),
);
$output = array();
foreach($input_data as $row_index => $row){
foreach($required_columns as $col_index => $column_name){
if( isset($row[$col_index]) ){
$output[$row_index][$column_name] = $row[$col_index];
}
}
}
print_r($output);
?>
I've used $row_index and $col_index for simplicity.
Original answer, for historical purposes only ;-)
I can't really understand your specs but PHP features variable variables:
<?php
$arr = array('foo', 'bar', 'bash', 'monkey', 'badger');
foreach($arr as $i){
$$i = $i;
}
?>
Now your script has these variables available: $foo, $bar... It's quite useless and potentially dangerous but it does what you seem to need.
You are trying to use a language construct in a manner in which it's not meant to be used. Use variable variables as Alvaro mentioned.
$arr = array('foo', 'bar', 'bash', 'monkey', 'badger');
foreach ($arr as $index => $key) {
$$key = $data[$index];
}
or
$arr = array('foo', 'bar', 'bash', 'monkey', 'badger');
$result = array();
foreach ($arr as $index => $key) {
$result[$key] = $data[$index];
}
extract($result);
In short, do not use "list", use arrays and associated arrays. Write helper functions to make your code clearer.
why not immediatly call the vars like
$arr['foo']
or
$arr[0]
If you want to extract the elements of $data into the current context, you can do that with extract. You might find it useful to call array_intersect_key first to pare down $data to the elements that you want to extract.
May be try like this :
$arr = array('foo', 'bar', 'bash', 'monkey', 'badger');
$data = "$".implode(",", $arr);
echo str_replace(",", ",$", $data);