randomize value in array for specific key - php

I'm trying to get a random array for specific key.
this is my code so far,
$convert = array(
'a' => 'Amusing','Amazing',
'b' => 'Beyond',
'c' => 'Clever','Colorful','Calm',
'd' => 'Dangerous','Donkey',
'e' => 'Endangered',
'f' => 'Fancy',
'g' => 'Great',
'h' => 'Helpful','Humorous',
);
$txt="baca";
$txt=strtolower($txt);
$arr=str_split($txt);
foreach ($arr as $alfa) {
echo $alfa." = ".$convert[$alfa]."\n";
}
the output would be :
b = Beyond
a = Amusing
c = Clever
a = Amusing
but I'm trying to get
b = Beyond
a = Amusing
c = Clever
a = Amazing
Unique value for specific array ('a') in this case.
I tried to use array_rand but failed. I would appreciate any advice given..

This:
array(
'a' => 'Amusing','Amazing',
...
)
is equivalent to:
array(
'a' => 'Amusing',
0 => 'Amazing',
...
)
You're not specifying a key for the word "Amazing", so it automatically gets a numeric key. It does not in any way actually belong to the 'a' key, even if you write it on the same line.
What you want is:
array(
'a' => array('Amusing', 'Amazing'),
...
)
And then:
$values = $convert['a'];
echo $values[array_rand($values)];

Related

Count unique values in a column of an array

I have an array like this:
$arr = [
1 => ['A' => '1', 'C' => 'TEMU3076746'],
2 => ['A' => '2', 'C' => 'FCIU5412720'],
3 => ['A' => '3', 'C' => 'TEMU3076746'],
4 => ['A' => '4', 'C' => 'TEMU3076746'],
5 => ['A' => '5', 'C' => 'FCIU5412720']
];
My goal is to count the distinct values in the C column of the 2-dimensional array.
The total rows in the array is found like this: count($arr) (which is 5).
How can I count the number of rows which contain a unique value in the 'C' column?
If I removed the duplicate values in the C column, there would only be: TEMU3076746 and FCIU5412720
My desired output is therefore 2.
Hope this simplest one will be helpful. Here we are using array_column, array_unique and count.
Try this code snippet here
echo count(
array_unique(
array_column($data,"C")));
Result: 2
combine array_map, array_unique, count
$array = [ /* your array */ ];
$count = count(
array_unique(
array_map(function($element) {
return $element['C'];
}, $array))))
or use array_column as suggested by sahil gulati, array_map can do more stuff which probably isn't needed here.
I had a very similar need and I used a slightly different method.
I have several events where teams are participating and I need to know how many teams there are in each event. In other words, I don't need to only know how many distinct item "C" there are, but how many items TEMU3076746 and FCIU5412720 there are.
The code will then be as is
$nbCs = array_count_values ( array_column ( $array, 'C' ) );
$nbCs will issue an array of values = Array([TEMU3076746] => 3 [FCIU5412720] => 2)
See example in sandbox Sandbox code
$data=array();
$data=[
1 => [
'A' => '1'
'C' => 'TEMU3076746'
]
2 => [
'A' => '2'
'C' => 'FCIU5412720'
]
3 => [
'A' => '3'
'C' => 'TEMU3076746'
]
4 => [
'A' => '4'
'C' => 'TEMU3076746'
]
5 => [
'A' => '5'
'C' => 'FCIU5412720'
]
];
$total_value=count(
array_unique(
array_column($data,"C")));
echo $total_value;
Most concisely, use array_column()'s special ability to assign new first level keys using the targeted column's values. This provides the desired effect of uniqueness because arrays cannot contain duplicate keys on the same level.
Code: (Demo)
echo count(array_column($arr, 'C', 'C')); // 2
To be perfectly clear, array_column($arr, 'C', 'C') produces:
array (
'TEMU3076746' => 'TEMU3076746',
'FCIU5412720' => 'FCIU5412720',
)
This would also work with array_column($arr, null, 'C'), but that create a larger temporary array.
p.s. There is a fringe case that may concern researchers who are seeking unique float values. Assigning new associative keys using float values is inappropriate/error-prone because the keys will lose precision (become truncated to integers).
In that fringe case with floats, fallback to the less performant technique: count(array_unique(array_column($arr, 'B))) Demo

php Sorting an array based upon key value of another array

I have one array:
$array_sorter = [
'XXS' => 1,
'XS' => 2,
'S' => 3,
'M' => 4,
'L' => 5,
'XL' => 6,
'XXL' => 7
];
and another one that could be like this:
$array_to_sort = ('XS','M','XL','S','L','XXS')
how can I do to sort the second one based upon the first one?
I mean:
$array_to_sort are sizes but they are random inside this array
I need to print the list of available sizes ($array_to_sort) but in the order of $array_sorter
As stated by #Jakumi, usort would be the way to go. However this way might be easier to understand if you are a beginner :
$array_sorter = [
'XXS' => 1,
'XS' => 2,
'S' => 3,
'M' => 4,
'L' => 5,
'XL' => 6,
'XXL' => 7,
];
$array_to_sort = array('XS', 'M', 'XL', 'S', 'L', 'XXS');
$array_sorted = array();
foreach($array_to_sort as $item){
$k = $array_sorter[$item];
$array_sorted[$k] = $item;
}
ksort($array_sorted);
Simply use the first array as a "weight"-provider. I mean the first array have a weight for every entry of your second array (e.g. M get the weight 4).
loop over the second array and create a thrid one: $weightArray like this:
$weightArray = array();
foreach($array_to_sort as $value){
$weight = $array_sorter[$value];
if(!isset($weightArray[$weight])){
$weightArray[$weight] = array();
}
$weightArray[$weight][] = $value;
}
Now you have an array like this: (2=>'XS', 4=>'M', 5=>'XL', 3=>'S', 5=>'L', 1=>'XXS')
now you can sort it by key ksort() and copy it back to your source array like this:
$array_to_sort = array_values(ksort($weightArray));
PS: if you have something like $array_to_sort = ('XS','M','M','M','L','XXS') it will also work => $array_to_sort = ('XXS','XS','M','M','M','L')
Thanks to all for you suggestion
I found alone this solution:
my mistake was focusing on the array to be sorted ($arrat_to_sort)
instead I turned the problem:
as $array_sorter always contains all possible values of $arrat_to_sort
in the right order, I used the function array_intersect($ array_sorter, $ arrat_to_sort)
and immediately I have an array with the values of $ arrat_to_sort in the $array_sorter position

Array keys get lost as they are considered numeric

Let's say there exists an array:
$array = array(
'1001' => 'a',
'1002' => 'b',
'1003' => 'c',
);
Now let's say someone wants reverse that array:
$array = array_reverse($array);
The problem is, that array_reverse seems to cast all numeric values to integers and then resets the indexes:
0 => 'c' - should be '1003' => 'c'
1 => 'b' - should be '1002' => 'b'
2 => 'a' - should be '1001' => 'a'
What someone may have also tried was this - but without any luck (as expected):
$array[(string) $index] = 'a';
You can even experience this yourself here on codepad.
How can this be solved? Do I have to write my own mapping function, which can handle this or is there any other way?
you just need to use the following code:
array_reverse($array, true)
As per php documentation, to preserve keys you must set 2nd parameter to true

filter an array by key value that has pipes in it

I have a form that will need to except input from users to filter the search results. I am not the original designer of the form. I one of two ways that I saw to filter the results. A) I could have tried to restrict the sql query to the selected codes or B) filter the results that are returned. I am trying B.
I have tried
var_dump(array_intersect_key($array1, $array2));
No success:
Array1 looks like this:
array (
'|00006|5' => array('pid' => 111
'provider_id' => 123456 )
'|93000|34' => array('pid' => 112
'provider_id' => 127654 )
'|93225|1' => array('pid' => 113
'provider_id' => 127893 )
)
I figured out how the pipes got into the key values and I tried to adjust my keys to match but that did not work either.
Any suggestions on how I can filter these types of results with a key that is not a single value and is dynamically changed?
Array2 look like:
99232 => string '99232' (length=5)
85610 => string '85610' (length=5)
93970 => string '93970' (length=5)
93000 => string '93000' (length=5)
99406 => string '99406' (length=5)
99215 => string '99215' (length=5)
I made the key value and the string value the same trying to setup some type of filtering.
But since the third value in array1 will be dynamically delivered in a while clause. I have no way of matching that number to the Array2.
My expected outcome is
array (
'|93000|34' => array('pid' => 112
'provider_id' => 127654 )
)
As that only one of the 6 inputs matched one of the array1 values.
You have to define your key comparison function and then use array_intersect_ukey():
$a = array (
'|00006|5' => array('pid' => 111,
'provider_id' => 123456 ),
'|93000|34' => array('pid' => 112,
'provider_id' => 127654 ),
'|93225|1' => array('pid' => 113,
'provider_id' => 127893 ),
);
$b = array('93000' => '93000');
print_r(array_intersect_ukey($a, $b, function($ka, $kb) {
if ($ka[0] == '|') { // transform key
$ka = substr($ka, 1, strrpos($ka, '|') - 1);
}
if ($kb[0] == '|') { // transform key
$kb = substr($kb, 1, strrpos($kb, '|') - 1);
}
// perform regular comparison
return strcmp($ka, $kb);
}));
or you can do this.
good luck :)
$parsed1 = array();
foreach($array1 as $key => $value) {
$splited = explode("|", $key);
$parsed1[$splited[1]] = $value;
}
var_dump(array_intersect_key($parsed1,$array2));

array values in multidimensional array

I have two arrays
they look like
$a1 = array(
array('num' => 1, 'name' => 'one'),
array('num' => 2, 'name' => 'two'),
array('num' => 3, 'name' => 'three'),
array('num' => 4, 'name' => 'four'),
array('num' => 5, 'name' => 'five')
)
$a2 = array(3,4,5,6,7,8);
I want to end up with an array that looks like
$a3 = array(3,4,5);
so basically where $a1[$i]['num'] is in $a2
I know I could do
$a3 = array();
foreach($a1 as $num)
if(array_search($num['num'], $a2))
$a3[] = $num['num'];
But that seems like a lot of un-needed iterations.
Is there a better way?
Ah Snap...
I just realized I asked this question the wrong way around, I want to end up with an array that looks like
$a3 array(
array('num' => 3, 'name' => 'three'),
array('num' => 4, 'name' => 'four'),
array('num' => 5, 'name' => 'five')
)
You could extract the relevant informations (the 'num' items) from $a1 :
$a1_bis = array();
foreach ($a1 as $a) {
$a1_bis[] = $a['num'];
}
And, then, use array_intersect() to find what is both in $a1_bis and $a2 :
$result = array_intersect($a1_bis, $a2);
var_dump($result);
Which would get you :
array
2 => int 3
3 => int 4
4 => int 5
With this solution :
you are going through $a1 only once
you trust PHP on using a good algorithm to find the intersection between the two arrays (and/or consider that a function developed in C will probably be faster than any equivalent you could code in pure-PHP)
EDIT after the comment : well, considering the result you want, now, I would go with another approach.
First, I would use array_flip() to flip the $a2 array, to allow faster access to its elements (accessing by key is way faster than finding a value) :
$a2_hash = array_flip($a2); // To speed things up :
// accessing by key is way faster than finding
// an item in an array by value
Then, I would use array_filter() to apply a filter to $a1, keeping the items for which num is in the $a2_hash flipped-array :
$result = array_filter($a1, function ($item) use ($a2_hash) {
if (isset($a2_hash[ $item['num'] ])) {
return true;
}
return false;
});
var_dump($result);
Note : I used an anonymous function, which only exist with PHP >= 5.3 ; if you are using PHP < 5.3, this code can be re-worked to suppress the closure.
With that, I get the array you want :
array
2 =>
array
'num' => int 3
'name' => string 'three' (length=5)
3 =>
array
'num' => int 4
'name' => string 'four' (length=4)
4 =>
array
'num' => int 5
'name' => string 'five' (length=4)
Note the keys are not corresponding to anything useful -- if you want them removed, just use the array_values() function on that $result :
$final_result = array_values($result);
But that's probably not necessary :-)

Categories