I have a large array in PHP, having near around 168000 keys and values. There is date (Y-m-d) and hour in key and numeric value in value.
So value is just a numeric.
And key is in Y-m-d_H format.
Array looks like following:
$input = array('2008-01-01_00' => 123, '2008-01-01_01' => 456, ...... , '2012-09-22_16' => 789);
I need to find the total of last month, last year, current year, current month and etc.
Which is the best way to find it? Please suggest.
What about this:
$results=array();
foreach ($input as $k=>$v) {
$date=explode('_',$k);
$date=explode('-',$date[0]);
//Store year
$key=$date[0];
if (!isset($results[$key])) $results[$key]=0;
$results[$key]+=$v;
//Store month
$key.='-'.$date[1];
if (!isset($results[$key])) $results[$key]=0;
$results[$key]+=$v;
//Store day
$key.='-'.$date[2];
if (!isset($results[$key])) $results[$key]=0;
$results[$key]+=$v;
}
print_r($results);
Change the keys to ints, e.g.
'2008-01-01_00' -> 2008010100
sort your array with ksort()
Then you can use quicksearch to find something between 2008010100 and 2009010100.
Also, Fastest is to traverse the array once and calculate all the statistics you need.
Break it down into manageable execution units and thread them ...
http://pthreads.org/
Related
I have a multi-D array like so:
array ( 'JD'=>2457002.50, 67.618536),
array ( 'JD'=>2457003.50, 67.619705),
array ( 'JD'=>2457004.50, 67.620938)....
I have a value say:
$MyJD = 2457003.9553;
I would like to find the value in the array, and if not, match the closest number to the array in question and return the the next index (which i'm assuming is [1])
I was thinking to do an array_search, but it's not going to find the exact number, I want the closest number to $MyValue?
This won't return the index but will return the proper array:
array_multisort(array_map(function($v) use($MyJD) {
return abs($v['JD'] - $MyJD);
}, $array), $array);
$result = reset($array);
Calculate the difference between each JD value and $MyJD
Sort on the difference (sorting the original) and get the lowest (first) one
Alternately, you could combine using the difference as the key and then sort on the keys:
$array = array_combine(array_map(function($v) use($MyJD) {
return abs($v['JD'] - $MyJD);
}, $array), $array);
ksort($array);
$result = reset($array);
Maybe someone will post a good array_reduce answer.
Do bucle put new array with key difference between
In this way you will have array ordered by difference
In each iteration
$myarray[myvalue - yourvalueinbucle] if -1 this key then ×-1 and how value your enter iterator of bucle, then your value for this key = your line multiarrayvalue in for each iterator
I have two array
$array1 = array("2017-12-08","2017-12-09","2017-12-10","2017-12-11","2017-12-12","2017-12-13","2017-12-14","2017-12-15","2017-12-16","2017-12-17","2017-12-18","2017-12-19","2017-12-20","2017-12-21","2017-12-22");
$array2 = array("Y","Y","Y","Y","Y","N","N","N","Y","Y","Y","N","N","Y","Y");
I need the first and last date where the key="Y". Like this:
$result = array("2017-12-08 - 2017-12-12", "2017-12-16 - 2017-12-18", "2017-12-21 - 2017-12-22");
How i can make this?
I have tried with array_combine but after that I do not know how to list the dates pairing.
Moved from answer
Yes this is a good idea, Justinas, but the result is not exactly what i need. Your result give me the first 2017-12-08 and the last 2017-12-22. But i need from all pairs the first and end date, like:
"2017-12-08 - 2017-12-12"
"2017-12-16 - 2017-12-18"
"2017-12-21 - 2017-12-22"
Because i need to insert in the db like
INSERT INTO $table start='firstDate' AND end='lastDate'.
And in this example 3 lines.
First find only array keys that contains value as Y:
$yes = array_filter($array2, function ($yn) {return $yn == 'Y'});
Now do $result = array_intersect_key($array1, $yes) to get dates that has Y in array2.
Finally get first (current($result)) and last end($result) dates.
Example
In the following array I have the number of days as the first value and the number of hours as the second value:
$myoptions = array (
array("1 day",24),
array("2 days",48),
array("3 days",72)
);
To get the second item from the array, I just do the following:
echo $myoptions[0][1]; // returns 48
So what can I do to search the array index above using one of the value? Let's say I need to know what is the number of hours for array = '3 days'.
You can use array_column like as
echo array_column($myoptions,1,0)['3 days'];//72
Demo
It's not likely that the array you showed us is really what you're after.
PHP's arrays are so-called associative arrays, meaning that you can use anything to index them, not just numbers:
$myoptions = array(
"1 day" => 24,
"2 days" => 48,
"3 days" => 72,
);
So,
echo $myoptions["3 days"]
or
$days = "3 days";
echo $myoptions[$days];
would directly return what you need. Of course, in real life applications, you would need to make sure that your input matches one of the indexes of the array.
Actually, but this is not something we can decide without knowing what you try to accomplish but in most cases you really need the opposite:
$myoptions = array(
24 => "1 day",
48 => "2 days",
72 => "3 days",
);
That is, your program stores and uses the numeric part, the number of hours internally, and whenever you need to display the option it represents to the user, you do the conversion to the human readable format, not the other way around.
There are probably better ways to design that array, but here's a function that should give you what you asked for:
function gethours($x, $myoptions){
foreach($myoptions as $o){
if($o[0] == $x){
return $o[1];
}
}
}
echo gethours('3 days', $myoptions);
If the column you search in is always the same you could just go for an associative array and use that column as array keys.
occurrence of A----5 times
occurrence of B----7 times
occurrence of C----6 times
($total['A']=5;
$total['B']=7;
$total['C']=6;)
I need to rate each based on their occurrence as follows,
$rating['A']=3;
$rating['B']=1;//most occurrence will get rate 1.
$rating['C']=2;
asort(&$total);
$rating = 1;
foreach (array_reverse($total) as $key => $val)
$total[$key] = $rating++;
You could also try using the array functions like sorting the values first and get keys of the sorted array and then create another array with the extracted keys as values. Now you get the same array with their rankings, except that you have '0' rank first as arrays start with an index 0.
May be you could pad an additional value with '0' an then finally remove it.
Something like this,
$total['A']=5;
$total['B']=7;
$total['C']=6;
$total[0]=0;
asort($total);
$total = array_slice(array_flip(array_keys($total)),1);
Or if you don't like to pad an extra value, you can try it this way. Create an array with the keys and the count of the sorted array.
asort($total);
$total = array_combine(array_keys($total),range(1, count($total)));
This might be a quick and easy way of doing. Hope this helps.
I've been given a datafile where the original creator used alphabetical rather than numeric values to show order.
For example, if there's ten items, they'd be named:
12342313A
12342313B
12342313C
12342313D
12342313E
...
I need to import these values into a mySQL table that has order as a required int column, and I need to convert the letter to a number.
Is there a function in PHP to get a numeric value for a letter? Or will I need to do a substr to grab the trailing letter, and create an indexed array of letters and just do a lookup against that array?
I'm hesitant to do the simple way above, since I don't know how many objects could potentially exist, and I could need to write an array from A-AAAA or something.
Try converting it from base 36 to base 10 using base_convert(), I.e. base_convert($str, 36, 10). You might need to strtolower it first, and it'll only work if its not case sensitive.
PHP has a simple way to create that array, so you could write a function to figure all that out for you and do something like:
function str_to_num($letters, $max = 'ZZZZZZ') {
$count = 0;
for ($i = 'A'; $i < $max; $i++) {
$count++;
if ($letters == $i)
return $count;
}
}
Then you could do the substr, find the letters at the end, and then pass it into the function:
str_to_num('A'); // returns 1
str_to_num('AB'); // returns 28
str_to_num('AC'); // returns 29
str_to_num('ABC'); // returns 731
Something like that, anyway.
Good luck.
Assuming this is a one-time problem that you've got to correct and won't encounter moving forward, I suggest you use sort to... erm, sort out the problem. Let's say you have all those alpha-numeric order fields in an array, like so:
$vals = array (
'12342313A',
'12342313D',
'12342313E',
'12342313B',
'12342313C'
);
Those are all mixed up, not in order. But, you can call the function sort (docs) on that array and PHP does a decent job of making sense out of it:
print '<pre>Unsorted: ';
print_r($vals);
print '</pre>';
sort($vals);
print '<pre>Sorted: ';
print_r($vals);
print '</pre>';
/*
Unsorted: Array
(
[0] => 12342313A
[1] => 12342313D
[2] => 12342313E
[3] => 12342313B
[4] => 12342313C
)
Sorted: Array
(
[0] => 12342313A
[1] => 12342313B
[2] => 12342313C
[3] => 12342313D
[4] => 12342313E
)
*/
So far, so good. Now, you've got them ordered, and as a bonus you can use the index of the array as your new field in the database. Alter the table and add a field to hold the new value; we'll call this field numeric_order, and in my sample I've called the field that currently holds the alpha-numeric sort data string_order. Loop your sorted array and update the database (for example):
foreach ($vals as $x=>$v) {
$sql = 'UPDATE myTable SET numeric_order = '.($x+1).' WHERE string_order = "'.$v.'"';
}
I add 1 to x in the loop based on the assumption that you don't want anything to have 0 for the order - if that isn't a concern, then you can just use x. This is also predicated on the assumption that no two rows have the same alpha-numeric sort value.
If they do, then all is not lost! Start with your array looking like this:
$vals = array (
3=>'12342313A',
15=>'12342313D',
66=>'12342313E',
101=>'12342313B',
200=>'12342313C'
);
... the numeric keys would represent the unique/primary key of the corresponding row. Instead of sort, which does not preserve keys, use asort (which does preserve keys - docs), and then your loop looks like this:
$ord = 1
foreach ($vals as $x=>$v) {
$sql = 'UPDATE myTable SET numeric_order = '.$ord.' WHERE id = "'.$x.'"';
$ord++;
}
If my base assumption is wrong, and you'll continue to deal with this method of ordering rows, then in my humble view you ought to re-consider your data design.
use ord() with substr and subtract 64. This will set A to 1, B to 2, etc...
From what you have above, it seems like your values (last digit, at least) can be thought as being hex numbers. You can then transform them into decimal numbers through the hexdec function.
http://php.net/manual/en/function.hexdec.php