I have array in php like
$randomarray = array('1106'=>'5','1110'=>'2','11867'=>'3','1206'=>'2','1210'=>'1','1223'=>'6','1235'=>'3','12565'=>'4','1258'=>'5','12690'=>'2','12693'=>'3','1283'=>'1','12944'=>'5');
I want to randomly pick elements from the array with the count of exactly 20. Each element have to only one time
I tried some array random example. I can't able to get the exact total which i expect.
this is the example of what i did that. But loop went to infinitive,
function randomTo($numIn) {
global $randomarray;
$numOut = 0;
$numbers = array();
do {
$key = array_rand($randomarray );
$add = $mainarray[$key];
if($numOut + $add > $numIn)
continue;
$numOut += $add;
$numbers[] = $add;
unset($mainarray[$key]);
} while( $numOut != $numIn );
return $numbers;
}
$testdata = randomTo(20);
The problem that you're trying to solve is called Subset sum and it's a subset of the Knapsack problem.
Just google for it, and while you're at it, google for Dynamic programming as it's a way of approaching the problem.
if(count($randomarray)) > 20
print_r(array_rand($randomarray, 20));
Get some Idea from this :
An example for getting random value from arrays
$r = array();
for ($i = 0; $i < $num; $i++) {
$r[] = $arr[$i];
}
return $num == 1 ? $r[0] : $r;
}
$a = array("apple", "banana", "cherry");
print_r(array_random($a));
print_r(array_random($a, 2));
?>
cherry
Array
(
[0] => banana
[1] => apple
)
And example for getting random value from assoc arrays;
<?php
function array_random_assoc($arr, $num = 1) {
$keys = array_keys($arr);
shuffle($keys);
$r = array();
for ($i = 0; $i < $num; $i++) {
$r[$keys[$i]] = $arr[$keys[$i]];
}
return $r;
}
$a = array("a" => "apple", "b" => "banana", "c" => "cherry");
print_r(array_random_assoc($a));
print_r(array_random_assoc($a, 2));
?>
Array
(
[c] => cherry
)
Array
(
[a] => apple
[b] => banana
)
Related
I'm trying to build a script that does two thing.
1) The Numbers should not repeat.
2) The numbers should be from an array called $id.
<?php
$a = array(); // final array which will have our id's to display
$id = array(1, 3, 5, 7, 9); //final array should contain a number only from this list
$itemstoshow = 3; // how many items to display
for($i = 0; $i < $itemstoshow; $i++) {
do {
$a[$i] = assignid(9);
$chkid = checkeer($a[$i], $i);
$chkdata = chkdata($a[$i], $i);
} while($chkdata == "nonexist" or $chkid == "repeatedid");
}
// display numbers in the array
for($i = 0; $i < $itemstoshow; $i++) {
echo "Item " . $a[$i] . "--------";
}
// check for redundancy function
function checkeer($x, $y)
{ //first parameter is query aray second is counter
global $a;
$err = 0;
// check if repeating number
for($i = 0; $i <= $y - 1; $i++) {
if($x == $a[$i]) {
$err = 1;
}
}
if($err == 1) {
return "repeatedid";
}
}
//check if array $a holds value from $id or not
function chkdata($x, $y)
{
global $a;
global $id;
for($i = 0; $i <= $y - 1; $i++) {
if($x !== $id[$i]) {
return "nonexist";
}
}
}
//assign id function
function assignid($x)
{
return rand(1, $x);
}
problem number 1 solved problem number 2 still not solved please help me.
the code should show 3 numbers from 1 to 9 which donot repeat and are in the array $id
You could use a combination of array_rand and array_map to get random values from the array that has the values your basing the randomization. Take a look:
$id = array(1,3,5,7,9); //final array should contain a number only from this list
$itemstoshow = 3;
$values = array_map(function($item) use($id){
return $id[$item];
}, array_rand($id, $itemstoshow));
print_r($values);
Output:
Array
(
[0] => 1
[1] => 3
[2] => 9
)
Running again:
Array
(
[0] => 3
[1] => 7
[2] => 9
)
You can use array_rand that selects random keys:
$id = array(1,3,5,7,9);
$result = array_intersect_key($id, array_flip(array_rand($id, 3)));
Or you can shuffle the array and take for example the 3 first items:
$id = array(1,3,5,7,9);
$temp = $id;
shuffle($temp);
for ($i = 0; $i < 3; $i++) {
$result[] = $temp[$i];
}
This question already has answers here:
Populate array of integers from a comma-separated string of numbers and hyphenated number ranges
(8 answers)
Closed 6 months ago.
I'm trying to normalize/expand/hydrate/translate a string of numbers as well as hyphen-separated numbers (as range expressions) so that it becomes an array of integer values.
Sample input:
$array = ["1","2","5-10","15-20"];
should become :
$array = [1,2,5,6,7,8,9,10,15,16,17,18,19,20];
The algorithm I'm working on is:
//get the array values with a range in it :
$rangeArray = preg_grep('[-]',$array);
This will contain ["5-10", "16-20"]; Then :
foreach($rangeArray as $index=>$value){
$rangeVal = explode('-',$value);
$convertedArray = range($rangeVal[0],$rangeVal[1]);
}
The converted array will now contain ["5","6","7","8","9","10"];
The problem I now face is that, how do I pop out the value "5-10" in the original array, and insert the values in the $convertedArray, so that I will have the value:
$array = ["1","2",**"5","6","7","8","9","10"**,"16-20"];
How do I insert one or more values in place of the range string? Or is there a cleaner way to convert an array of both numbers and range values to array of properly sequenced numbers?
Here you go.
I tried to minimize the code as much as i can.
Consider the initial array below,
$array = ["1","2","5-10","15-20"];
If you want to create a new array out of it instead $array, change below the first occurance of $array to any name you want,
$array = call_user_func_array('array_merge', array_map(function($value) {
if(1 == count($explode = explode('-', $value, 2))) {
return [(int)$value];
}
return range((int)$explode[0], (int)$explode[1]);
}, $array));
Now, the $array becomes,
$array = [1,2,5,6,7,8,9,10,15,16,17,18,19,20];
Notes:
Casts every transformed member to integer
If 15-20-25 is provided, takes 15-20 into consideration and ignores the rest
If 15a-20b is provided, treated as 15-20, this is result of casing to integer after exploded with -, 15a becomes 15
Casts the array keys to numeric ascending order starting from 0
New array is only sorted if given array is in ascending order of single members and range members combined
Try this:
<?php
$array = ["1","2","5-10","15-20"];
$newdata = array();
foreach($array as $data){
if(strpos($data,'-')){
$range = explode('-', $data);
for($i=$range[0];$i<=$range[1];$i++){
array_push($newdata, $i);
}
}
else{
array_push($newdata, (int)$data);
}
}
echo "<pre>";
print_r($array);
echo "</pre>";
echo "<pre>";
print_r($newdata);
echo "</pre>";
Result:
Array
(
[0] => 1
[1] => 2
[2] => 5-10
[3] => 15-20
)
Array
(
[0] => 1
[1] => 2
[2] => 5
[3] => 6
[4] => 7
[5] => 8
[6] => 9
[7] => 10
[8] => 15
[9] => 16
[10] => 17
[11] => 18
[12] => 19
[13] => 20
)
Problem solved!
Using range and array_merge to handle the non-numeric values:
$array = ["1","2","5-10","15-20"];
$newArray = [];
array_walk(
$array,
function($value) use (&$newArray) {
if (is_numeric($value)) {
$newArray[] = intval($value);
} else {
$newArray = array_merge(
$newArray,
call_user_func_array('range', explode('-', $value))
);
}
}
);
var_dump($newArray);
It's easier to find out the minimum and maximum value and create the array with them. Here's an example:
$in = ["1","2","5-10","15-20"];
$out = normalizeArray($in);
var_dump($out);
function normalizeArray($in)
{
if(is_array($in) && sizeof($in) != 0)
{
$min = null;
$max = null;
foreach($in as $k => $elem)
{
$vals = explode('-', $elem);
foreach($vals as $i => $val)
{
$val = intval($val);
if($min == null || $val < $min)
{
$min = $val;
}
if($max == null || $val > $max)
{
$max = $val;
}
}
}
$out = array();
for($i = $min; $i <= $max; $i++)
{
$out[] = $i;
}
return $out;
}
else
{
return array();
}
}
here you go mate.
<?php
$array = ["1","2","5-10","15-20"];
$newArr = array();
foreach($array as $item){
if(strpos($item, "-")){
$temp = explode("-", $item);
$first = (int) $temp[0];
$last = (int) $temp[1];
for($i = $first; $i<=$last; $i++){
array_push($newArr, $i);
}
}
else
array_push($newArr, $item);
}
print_r($newArr);
?>
Simpler and shorter answer.
See in Ideone
$new_array = array();
foreach($array as $number){
if(strpos($number,'-')){
$range = explode('-', $number);
$new_array = array_merge($new_array, range($range[0],$range[1]));
}
else{
$new_array[] = (int) $number;
}
}
var_dump($new_array);
try this:
$array = ["1","2","5-10","15-20"];
$result = [];
foreach ($array as $a) {
if (strpos($a,"-")!== false){
$tmp = explode("-",$a);
for ($i = $tmp[0]; $i<= $tmp[1]; $i++) $result[] = $i;
} else {
$result[] = $a;
}
}
var_dump($result);
you did not finish a little
$array = ["1","2","5-10","15-20"];
// need to reverse order else index will be incorrect after inserting
$rangeArray = array_reverse( preg_grep('[-]',$array), true);
$convertedArray = $array;
foreach($rangeArray as $index=>$value) {
$rangeVal = explode('-',$value);
array_splice($convertedArray, $index, 1, range($rangeVal[0],$rangeVal[1]));
}
print_r($convertedArray);
I have been asked a question in an interview to sort a string by length of its words in php without using built in functions.No idea how to do this. Can somebody help me with this?
String: Sort a string by length of its words
Thanks in advance
$array = array('harish', 'mohan', 'jaideep', 'hari');
for ($i = 1; $i < count($array); $i++) {
for ($j = $i; $j > 0; $j--) {
if (strlen($array[$j]) < strlen($array[$j - 1])) {
$tmp = $array[$j];
$array[$j] = $array[$j - 1];
$array[$j - 1] = $tmp;
}
}
}
var_dump($array);
you could try this:
$string = "this is my test string";
$array = explode(" ", $string);
$result = array();
foreach ($array as $key => $string){
$counter = 0;
for($i = 0;;$i++){
if (!isset($string[$i])){
break;
}
$counter++;
}
$result[$counter][] = $string;
}
This splits your string and puts it into an array, where the keys are the counted characters. The problem now is, that you need to sort the array by the keys, which can be acquired by using ksort.
I do not know if you may use it, if not, refer to this answer (use of sort) or this answer (no sort), this should do the trick (though I didn't test it).
This is the solution that I propose. I added some comments.
<?php
/* First part split the string in their words and store them in an array called $words.
* The key is the length of the word and the value is an array with all the words having the same length as the key.
* e.g
* Array
(
[4] => Array( [0] => Sort )
[1] => Array( [0] => a )
[6] => Array( [0] => string, [1] => length)
[2] => Array( [0] => by, [1] => of)
[3] => Array( [0] => its )
)
*/
$str = "Sort a string by length of its words";
$word = '';
$i = 0;
$word_length = 0;
$words = [];
$max = -1;
while( isset($str[$i]) ) {
if( $str[$i] !== ' ' ){
$word .= $str[$i];
$word_length++;
}else{
//This is going to save the size of the longhest word in the array:
$max = ($word_length > $max) ? $word_length : $max;
//store the
$words[$word_length][] = $word;
$word = '';
$word_length = 0;
}
$i++;
}
//print_r($words); // uncomment this if you wanna see content of the array.
//The if-condition is for ascending order or descending order.
$order = "DESC"; // "ASC" | "DESC"
$res = '';
if( $order === "DESC") {
for( $i = $max; $i>=0 ; $i--) {
if( ! isset($words[$i]) ) { continue; }
foreach($words[$i] as $word){
$res .= $word . ' ';
}
}
}else {
//ascending order:
for( $i = 0; $i<=$max; $i++) {
if( ! isset($words[$i]) ) { continue; }
foreach($words[$i] as $word){
$res .= $word . ' ';
}
}
}
echo $res . "\n";
?>
Is this what you want?
Note: isset, echo, print, etc are PHP language constructs whereas print_r(), strlen(), etc. are built in functions. If you have doubts, you can see what's the difference in this post. What is the difference between a language construct and a "built-in" function in PHP?
I have a challenge multiplying two arrays.
this is what i intend doing
Array1 ( [0] => 2 [1] => 2 )
Array2 ( [0] => 8000.00 [1] => 1234.00 )
Every time i multiply this it breaks it down into 4 and returns a result as this
Array ( [0] => 16000 [1] => 16000 [2] => 2468 [3] => 2468 )
However when i pass single a single data it gets it right.
Here is my code, i'll appreciate any help i can get. Thanks
$total = array();
foreach($office_price as $price){
foreach($office_quantity as $quantity){
$total[] = $price * $quantity;
}
}
You can give multiple arrays to array_map, and it will process the corresponding elements:
$total = array_map(function($x, $y) { return $x * $y; },
$office_price, $office_quantity);
You loop through both arrays, so you get every value twice.
As you know, an array is built up using keys and values.
Use your foreach to that extent:
$total = array();
foreach ($office_price as $key=>$price) {
$total[] = $price * $office_quantity[$key];
}
You only need to loop one array, and by using the value from the second array with the same key, you get the proper result.
Use Array map function it will works
$total_hours = array(10, 20, 30);
$hourly_rate = array(15, 10, 15);
$total_pay = array_map(function($hour, $rate) {
return $hour * $rate;
}, $total_hours, $hourly_rate);
$total_in_array = array_map(function($x, $y) { return $x * $y; }, $office_price, $office_quantity); // This will return array of multiplied numbers
$total = array_sum($total_in_array); // This will return the total
Use this
$total = array();
for($i=0;$i<count($office_price);$i++){
$total[] = $office_price[$i] * $office_quantity[$i];
}
To multiply two arrays, you must do it elementwise: no nested loops involved. For example, if you want to get $total[2], then its value is $office_price[2] * $office_quantity[2]. Thus the one foreach loop. To loop through keys, use ... as $key => $price.
$office_price = array(10, 100, 1000);
$office_quantity = array(1, 2, 3);
$total = array();
foreach($office_price as $key => $price){
$total[$key] = $price * $office_quantity[$key];
}
var_dump($total);
// array(3) { [0]=> int(10) [1]=> int(200) [2]=> int(3000) }
$a= array (2,2);
$b= array(8000,1234);
$total = array();
for ($i=0;$i<count($a);$i++) {
$total[] = $a[$i] * $b[$i];
}
function a($a, $b)
{
$r = [];
for($i = 0; $i < (count($a)); $i ++)
{
$r[] = $a[$i] * $b[$i];
}
return $r;
}
I am struggling to know where to start when trying to assign ranks to the numeric values in an array when there are ties. So, for example, I need to turn an array like the following:
myarray = (4,76,34,13,34)
into another array like:
myarray2 = (1,5,3.5,2,3.5)
Basically, when the same number occurs more than once in the array, the assigned rank to those numbers is the average of the ranks. So, instead of the two 34s being ranked 3 and 4 they both get assigned 3.5. Similarly, if there were 3 copies of 34 then the 3 assigned ranks would be divided by 3. Any help would be much appreciated!
Many thanks,
Adam
I had fun with this one!
function rank($input)
{
$output = array();
$ranking = $input; sort($ranking); $ranking = array_flip($ranking);
$last_val = -1;
foreach($ranking as $key => $val){
$repetitions = ($val-$last_val-1);
$last_val = $val;
if($repetitions) {
$ranking[$key] = (($val*($repetitions+1))-($repetitions+1)*(($repetitions)/2))/($repetitions+1)+1 ;
} else {
$ranking[$key] = $val+1;
}
}
foreach($input as $key => $val){
$output[$key] = $ranking[$val];
}
return $output;
}
Use it like this:
$a = array(4,76,34,13,34);
$c = rank($a);
print_r($c);
will output:
Array
(
[0] => 1
[1] => 5
[2] => 3.5
[3] => 2
[4] => 3.5
)
wich is the same as:
Array(1, 5, 3.5, 2, 3.5)
as expected!
Here is one way to do it.
<?php
$myarray = array(4,76,34,13,34);
$sorted_array = $myarray;
$grouped_array = array();
sort($sorted_array);
foreach ($sorted_array as $rank => $entry) {
// Initialize the entry if it doesn't already exist
if (empty($grouped_array[$entry])) {
$grouped_array[$entry]['count'] = 1.0;
$grouped_array[$entry]['total'] = $rank + 1; // Account for 0-based array
} else {
$grouped_array[$entry]['count'] += 1.0;
$grouped_array[$entry]['total'] += $rank + 1; // Account for 0-based array
}
}
$myarray2 = array();
foreach ($myarray as $entry) {
// Get the average
$myarray2[] = $grouped_array[$entry]['total'] / $grouped_array[$entry]['count'];
}
I assume you also need to handle the cases where there are three or four or n values tied at the same rank.
I'm no PHP guru, but here's an approach (pseudo code) to defining a rank function:
define a = original array
define s = a.Sorted
define rank(n) = (s.FirstIndexOf(n) + s.LastIndexOf(n)) / 2
You may need to work a few examples on paper to convince yourself that this works even for triples and higher; it's reliant on s being sorted so that duplicates are adjacent.
The accepted solution (and others too) seem to be way more complicated than they need to be:
function Rank($data) {
$count = 0;
$unique = $data; sort($unique);
$unique = array_count_values($unique);
foreach ($unique as $key => $frequency) {
foreach (range(1, $frequency) as $i) {
$unique[$key] += $count++;
}
$unique[$key] /= $frequency;
}
foreach ($data as $key => $value) {
$data[$key] = $unique[$value];
}
return $data;
}
Example (demo):
print_r(Rank(array(4, 76, 34, 13, 34))); // 1; 5; 3.5; 2; 3.5
print_r(Rank(array(4, 76, 34, 13, 34, 34))); // 1; 6; 4; 2; 4; 4