I have array which have in letter format key.
'A' => array('WORD1','WORD2','WORD3'),
'B' => array('WORD1','WORD2','WORD3'),
'C' => array('WORD1','WORD2','WORD3'),
'D' => array('WORD1','WORD2','WORD3'),
'E' => array('WORD1','WORD2','WORD3'),
'F' => array('WORD1','WORD2','WORD3'),
'H' => array('WORD1','WORD2','WORD3'),
'G' => array('WORD1','WORD2','WORD3'),
...
I need to pick random value from each element. Example, when I set $output = "FGH"
Output will be:
F - (RANDOM WORD FROM ARRAY KEY F)\n
G - (RANDOM WORD FROM ARRAY KEY F)\n
H - (RANDOM WORD FROM ARRAY KEY H)\n
I used my code below but doesn't work..
$result = array();
foreach($chars as $char){
$random_key = array_rand($words[$char]); // get random key
$key = $words[$char][$random_key]; // get the word
unset($words[$char][$random_key]); // unset it so that it will never be repeated
$result[$key] = $char; // push it inside
}
Thanks to anyone that would help me
This gives a random word from whichever keys are specified in $output (note I have modified your $chars array slightly to make it obvious which value is being returned):
$chars = array(
'A' => array('A_WORD1','A_WORD2','A_WORD3'),
'B' => array('B_WORD1','B_WORD2','B_WORD3'),
'C' => array('C_WORD1','C_WORD2','C_WORD3'),
'D' => array('D_WORD1','D_WORD2','D_WORD3'),
'E' => array('E_WORD1','E_WORD2','E_WORD3'),
'F' => array('F_WORD1','F_WORD2','F_WORD3'),
'G' => array('G_WORD1','G_WORD2','G_WORD3'),
'H' => array('H_WORD1','H_WORD2','H_WORD3')
);
$output = 'FGH';
$result = array();
foreach(str_split($output) as $key) {
$result[] = $chars[$key][array_rand($chars[$key])];
}
var_dump($result);
The secret sauce here is the str_split() function.
<?php
$a=array("red","green","blue","yellow","brown");
$random_keys=array_rand($a,3);
echo $a[$random_keys[0]]."<br>";
echo $a[$random_keys[1]]."<br>";
echo $a[$random_keys[2]];
?>
for your reference : http://php.net/manual/en/function.array-rand.php
If you have already set up the random arrays to pick words from, it's quite straight forward with count() and rand().
//$globalWordArray = .......;
$selectedArray = array('B','D','F');
$wordList = array();
foreach($selectedArray as $words){
$wordList[] = $globalWordArray[$words][rand(0,count($globalWordArray[$words])-1];
}
This could be a solution:
$letters = array(
'A' => array('WORD1','WORD2','WORD3'),
'B' => array('WORD1','WORD2','WORD3'),
'C' => array('WORD1','WORD2','WORD3'),
'D' => array('WORD1','WORD2','WORD3'),
'E' => array('WORD1','WORD2','WORD3'),
'F' => array('WORD1','WORD2','WORD3'),
'H' => array('WORD1','WORD2','WORD3'),
'G' => array('WORD1','WORD2','WORD3'),
);
$output = "FGH";
for ($i=0; $i < strlen($output); $i++) {
echo $output[$i] ." - (RANDOM WORD FOR ARRAY KEY " . $output[$i]." ";
echo $letters[$output[$i]][array_rand($letters[$output[$i]])] .")" . "<br />";
}
Output is:
F - (RANDOM WORD FOR ARRAY KEY F WORD3)
G - (RANDOM WORD FOR ARRAY KEY G WORD3)
H - (RANDOM WORD FOR ARRAY KEY H WORD1)
Your logic looks wrong where you are actually performing the randomisation, see comments in your code below
$result = array();
foreach($chars as $char){
$random_key = array_rand($words[$char]);
$key = $words[$char][$random_key]; // This is a value at this point yet you named it key
unset($words[$char][$random_key]);
$result[$key] = $char; // This will create an entry in result such as $result['WORD 1'] = 'F', I'm sure thats wrong
}
Fixed version below
$result = array();
foreach($chars as $char){
$random_key = array_rand($words[$char]);
$value = $words[$char][$random_key];
unset($words[$char][$random_key]);
$result[$char] = $value;
}
What you have suggested you want is commonly referred to as a Shuffle Bag (http://kaioa.com/node/89). Shuffle Bags allow you to fill up collections with items and then pick them out randomly until the collection runs out of items. Think of it like the Bag of letters in Scrabble. There is a PHP implementation in the link above.
Using that sort of implementation would turn your foreach loop to this:
$result = array();
foreach($chars as $char){
$result[$char] = $words[$char]->next();
}
Related
I am trying to figure out how I can start looping through an array at a different index but when it reaches the end it loops back to the beginning and finishes the array. Basically, I need to be able to dynamically change the offset of the array.
What I am trying to do it associate a letter of the alphabet with a different alphabet letter to mix things up for a string.
Let's say I have a random array like so
$arr = array('a' => 'g', 'b' => 'w', 'c' => 'j', 'd' => 'y', 'e' => 'k');
Then I have a string like so
$string = 'abcde';
And let's say I need to start at index in the array at 2 which would be 'c' => 'j' then finish the array to the end and then loop back to the beginning until it is finished.
What I want to do is replace each letter with the corresponding letter associated with it in the array. So the final string after it is replaced would look like
I would reconstruct the array with
$build = strtr($string,$arr);
which would echo gwjyk
But I need to start at a random point in the array and then finish it and go back to the beggining and finish the entire array.
So maybe I have an offset of 2.
$offset = 2;
As I mentioned in the comments, I would approach this using array_slice and then merging the two arrays in order to simply get a new array, then loop through it from start to finish.
Here's a fully functional solution (and a runnable version)- although I'd like to point out that the offset really doesn't change the results at all:
/**
* Goes through a string and replaces letters based on an array "map".
*
* #param string - $string
* #param int - $offset
*
* #return string
*/
function change_letters( $string, $offset ) {
$letters = ['a' => 'g', 'b' => 'w', 'c' => 'j', 'd' => 'y', 'e' => 'k'];
// some defensive code to prevent notices or errors
if ( (int)$offset > count($letters)) {
echo '<p>Error: Offset is larger than the array of letters!</p>';
return $string;
}
// build new array based on passed-in offset
$new_array = array_slice($letters, $offset) + array_slice($letters, 0, $offset);
// at this point, array is ['c' => 'j', 'd' => 'y', 'e' => 'k', 'a' => 'g', 'b' => 'w']
// loop through the letters to replace...
foreach($new_array AS $from => $to) {
// swaps all instances of the "from" letter to the "to" letter in the string.
// NOTE: this could be easily modified to only replace n instances of the "from" letter
// like so: $string = str_ireplace( $from, $to, $string, 1); - would only replace 1 instance
$string = str_ireplace( $from, $to, $string );
}
return $string;
}
// Sample usage:
$word = 'abcde';
$new_word = change_letters( $word, 2); // "gwjk"
var_dump(2, $new_word);
$new_word = change_letters( $word, 5); // "gwjk"
var_dump(5, $new_word);
$new_word = change_letters( $word, 6); // "abcde"
var_dump(5, $new_word);
You can try:
<?php
$arr = array(1 => 2, 3 => 4, 5 => 6, 7 => 8, 9 => 0);
$STARTING_KEY = 3;
$array_keys = array_keys($arr);
$starting_index = array_search($STARTING_KEY, $array_keys);
for ($i = $starting_index; $i < sizeof($arr); $i++) {
echo $arr[$array_keys[$i]] . "\n";
}
for ($i = 0; $i < $starting_index; $i++) {
echo $arr[$array_keys[$i]] . "\n";
}
This will test all possible offsets for the string
$arr = array('a' => 'g', 'b' => 'w', 'c' => 'j', 'd' => 'y', 'e' => 'k');
$str = "abcde";
$strlen = strlen($str);
$keys = array_keys($arr);
for ($j = 0; $j < $strlen; $j++)
{
$startIndex = $j;
echo "offset: " . $startIndex . ": ";
for ($i = $startIndex; $i < $strlen; $i++ )
{
$char = substr( $str, $i, 1 );
echo $arr[$char];
}
for ($i = 0; $i < $startIndex; $i++ )
{
$char = substr( $str, $i, 1 );
echo $arr[$char];
}
echo "\n";
}
Output:
offset: 0: gwjyk
offset: 1: wjykg
offset: 2: jykgw
offset: 3: ykgwj
offset: 4: kgwjy
As mentioned in the comment, another option for your example data could be using array_slice and setting the offset and the length parameters and use array_merge:
$arr = array('a' => 'g', 'b' => 'w', 'c' => 'j', 'd' => 'y', 'e' => 'k');
$top = array_slice($arr, 0, 2);
$rest = array_slice($arr, 2);
print_r(array_merge($rest, $top));
Array
(
[c] => j
[d] => y
[e] => k
[a] => g
[b] => w
)
All that array slicin’n’dicing or using two loops to loop from x to end first, and start up to x second, is fine … but they don’t make for the most readable code IMHO.
Such an “offsetted circling-through” can be achieved in a quite trivial way with a numerically indexed array - a simple for loop, and the index “clamped down” by using modulo with the total number of array elements.
So in a case like this, I would perhaps prefer the following approach:
$arr = array('a' => 'g', 'b' => 'w', 'c' => 'j', 'd' => 'y', 'e' => 'k');
$c = count($arr);
$search = array_keys($arr);
$replace = array_values($arr);
$offset = 2; // zero-based
for( $i = 0; $i < $c; ++$i ) {
$idx = ( $i + $offset ) % $c;
echo $search[$idx] . ' => ' . $replace[$idx] . "<br>\n";
}
// result:
// c => j
// d => y
// e => k
// a => g
// b => w
How to get next value of a value from array.
I have one array like this
$items = array(
'1' => 'two',
'9' => 'four',
'7' => 'three',
'6'=>'seven',
'11'=>'nine',
'2'=>'five'
);
how to get next value of 'four' or 'nine'.
I have this
$input = "nine";
$items = array(
'1' => 'two',
'9' => 'four',
'7' => 'three',
'6'=>'seven',
'11'=>'nine',
'2'=>'five'
);
$keys = array_keys($items);
$size = count($keys);
$foundKey = array_search($input,$items);
if($foundKey !== false)
{
$nextKey = array_search($foundKey,$keys)+1;
echo "your input is: ".$input."\n";
echo "it's key is: ".$foundKey."\n";
if($nextKey < $size)
{
echo "the next key => value is: ".$keys[$nextKey]." => ".$items[$keys[$nextKey]]."\n";
}
else
{
echo "there are no more keys after ".$foundKey;
}
}
the idea is that because the keys are not in any real order i need to make an easy to traverse order by getting all the keys and putting them into an array so that their integer keys are our order. this way '1' = 0, '9' = 1, '11' = 4.
from there i then locate which key matches our input. if i find it i get the position of that key and + 1 (the next key). from there i can reference the data in $items using the string value in $keys at the position of our input +1.
if our input is 'five' we run into a problem as 'five' is the last value in our array. so the last if statement checks if the index for the next key is less than the number of keys since the largest index we'll have is 5 and the number of keys we have is 6.
while you could use array_values to get all the values into an array using ordered integer keys by doing this you loose your original keys unless you also used array_keys. if you use array_keys first then there's really no need to use array_values
hope this help:
while (($next = next($items)) !== NULL) {
if ($next == 'three') {
break;
}
}
$next = next($items);
echo $next;
for large array u can use :
$src = array_search('five',$items); // get array key
$src2 = array_search($src,array_keys($items)); // get index array (start from 0)
$key = array_keys($items); // get array by number, not associative anymore
// then what u need just insert index array+1 on array by number ($key[$src2+1])
echo $items[$key[$src2+1]];
If that's the case, you should first prepare your array. Based on your given array, it seems the index is not consecutively correct. Try using array_values() function.
$items = array(
'1' => 'two',
'9' => 'four',
'7' => 'three',
'6'=>'seven',
'11'=>'nine',
'2'=>'five'
);
$new_items = array_values($items);
$new_items = array(
[0] => 'two',
[1] => 'four',
[2] => 'three',
[3] => 'seven',
[4] => 'nine',
[5] =>'five'
);
Then you can do the foreach..
foreach($new_items as $key => $value) {
// Do the code here using the $key
}
I have this string of random numbers that needs to have some of the integers converted into letters. Notice that it takes two positions in the string to make a letter.
01110413 Original string
This string should ultimately be converted into this:
A11D13 Converted string
Here is my code so far
$id = '01110413';
$chg = array(0 => array(0, 1), 3 => array(4, 5));
$ltr = array(00 => 'A', 01 => 'B', 03 => 'C', 04 => 'D');
$id = str_split($id);
foreach($chg as $ltrpos => $val){
// $ltrpos; letter position placement in string AFTER conversion to letter
$ltrkey = null;
foreach($val as $idkey){
$ltrkey .= $id[$idkey];
unset($id[$idkey]);
if(!empty($ltrkey)){
$out[$ltrpos] = $ltr[(INT)$ltrkey];
}
}
}
Running this code gives:
Array
(
[0] => B
[3] => D
)
I need to insert these new values in the place where the old integer values were. The $chg array key is the position where the values should be in the converted string.
How can I order my final $out array so that the integers that were unset are replaced with the converted letters in their place?
This should do it:
$id = '01110413';
// your string codes always take up two positions, so you just need to provide the final position in the string
$chg = array(0,3);
// You could actually change 00 to just 0 (since they're integers). Also, later in the script, the two character position is cast to an int, so it will match these values.
$ltr = array(00 => 'A', 01 => 'B', 03 => 'C', 04 => 'D');
$converted_id = doConvert($id, $ltr, $chg);
function doConvert($id, $conversion_codes, $final_position) {
if( count($final_position) == 0 ) return $id;
$next_pos = array_shift($final_position);
// convert the two characters at the next position to a letter
$id = substr($id, 0, $next_pos) . $conversion_codes[(int) substr($id, $next_pos, 2)] . substr($id, $next_pos+2); // (cast to an (int) so it will match the keys in our conversion array)
return doConvert($id, $conversion_codes, $final_position);
}
Output of this example is:
B11D13
You say the first value should be A, but 01 => B, that's why the first letter is B.
If every two characters in your original id is a code, you can use something more general, like this:
$id = '01110413';
$conversion = array('00' => 'A', '01' => 'B', '03' => 'C', '04' => 'D');
$converted_id = "";
for($i=0; $i < strlen($id); $i+=2) {
$char_code = substr($id, $i, 2);
// we don't know this code, just append it
if( empty($conversion[$char_code]) ) {
$converted_id .= $char_code;
}
// convert and append
else {
$converted_id .= $conversion[$char_code];
}
}
We all know that arrays are actually ordered trees in PHP. Given that, an array index (integer key) need not be in any strict order or even exist at all. So, given an array like:
array( 1 => 'A', 5 => 'B', 2 => 'C', 3 => 'D', 6 => 'E', 0 => 'F' )
How can we determine the lowest (non negative) integer of the first empty key, without re-indexing the array? In this case it would be 4.
Easy solution by while loop:
function firstFreeKey($array)
{
$i = 0;
while(isset($array[$i])) $i++;
return $i;
}
$array = array( 1 => 'A', 5 => 'B', 2 => 'C', 3 => 'D', 6 => 'E', 0 => 'F' );
echo firstFreeKey($array);
Output:
4
$a = array( 1 => 'A', 5 => 'B', 2 => 'C', 3 => 'D', 6 => 'E', 0 => 'F' );
for($i = 0, $l = count($a); $i < $l; $i++) if(!array_key_exists($i, $a)) break;
echo $i; // 4
First method is getting fancy with arrays.
// STUPID FANCY WAY (playing with arrays)
$array = array( 1 => 'A', 5 => 'B', 2 => 'C', 3 => 'D', 6 => 'E', 0 => 'F' );
// fetch existing keys
$keys = array_keys($array);
// build a range with all keys (between min and max)
$keys_all = range(min($keys), max($keys));
// difference between all and existing
$keys_diff = array_diff($keys_all, $keys);
// fetch the first in difference (min)
$min_key = reset($keys_diff);
// output it
var_dump($min_key);
Second method is actually viable as it spares the need for extra arrays in memory.
// PROPER WAY (not extra array operations)
$array = array( 1 => 'A', 5 => 'B', 2 => 'C', 3 => 'D', 6 => 'E', 0 => 'F' );
// fetch existing keys
$keys = array_keys($array);
// nullify first
$min_key = null;
// loop all keys and find missing one (skip 1st and last, they totally exist!)
for($key = ($min = min($keys)) + 1, $max = max($keys); $key < $max; ++$key){
if(!isset($array[$key])){
$min_key = $key;
break;
}
}
// output it
var_dump($min_key);
I'll explain if comments are not enough.
PS: This method handles situation when minimum key value is not 0. Hence it's independent of range min and max. And keys need to be integers, obviously.
Have you tried something like
echo min(array_keys($array));
array_keys returns the list of keys for the array, and min determines the lowest value in the array.
Expanding following comments :
As the array is a continous int value, you can do the following
$keys = array_keys($array);
$arr2 = range(0,max($keys));
// diff gets the missing elements
$missing = array_diff($arr2,$keys);
echo $missing[0];
Not sure on the performance of this vs brute force, but it can be tested.
Possibly one of the longest answers, but the most explained.
$Jumbled_Arr = array(
1 => "test",
3 => "another",
4 => "t",
7 => "kfkfk",
9 => "fk"
);
function GetMissingKey($Array,$Return_Type = false){
// Get the Maximum Key Value
$Max_Key = max(array_keys($Array));
// Treat this as the default array index, as all numerical arrays start at a 0 key set
$Counter = 0;
// A Blank array to be maniuplated
$Generated_Array = array();
// Generate a full array based on the maximum value and the array index, this will create a keyset from 0 to the highest value
while ($Counter < $Max_Key){
$Generated_Array[] = $Counter;
$Counter++;
}
// Discover the differences between the correctly formed array and the specified array keys
$Missing_Key = array_diff($Generated_Array,array_keys($Array));
// Work with the second parameter, as the settings.
if ($Return_Type === true){
// If set to true, we are expecting more than 1 free key within the array, so we will return the entire array
return $Missing_Key;
}elseif ($Return_Type === false){
// If set to false (or blank) we are expecting a single free key to be discovered & we will return it as an imploded array
return implode($Missing_Key);
}
}
print_R(GetMissingKey($Jumbled_Arr,true));
If true is passed through to this function, you will be returned with an array of missing keys.
If false is passed through, then you will be returned with a single integer (careful when if expecting more than one key to be returned).
$foo = array(1 => 'A', 5 => 'B', 2 => 'C', 3 => 'D', 6 => 'E', 0 => 'F');
$bar = array(1 => 'A', 4 => 'Z', 2 => 'L', 3 => 'N');
function firstFreeKey($array)
{
ksort($array);
for ($i = 0; $i <= count($array); $i++) {
if (!isset($array[$i])) {
return $i;
}
}
return count($array) + 1;
}
function firstFreeKeyNotZero($array)
{
$i = min(array_keys($array));
while (isset($array[$i])) {
$i++;
}
return $i;
}
echo firstFreeKey($foo); //returns 4
echo firstFreeKey($bar); //returns 0
echo firstFreeKeyNotZero($foo); //returns 4
echo firstFreeKeyNotZero($bar); //returns 5
Edit: Added case where not starting from 0, as requested by CodeAngry
To get all free keys:
$aArray = array(1 => 'A', 5 => 'B', 2 => 'C', 3 => 'D', 6 => 'E');
$iMaxKey = 7; //max key you will need
$aAllKeys = range(0, iMaxKey); //create array(0,1,2,3,4,5,6,7);
$aAllFreeKeys = array_diff_key($aAllKeys, $aArray); //will be: array(0,4,7);
and now if you need first free key:
$iKey = array_shift($aAllFreeKeys);
i have this string -
$result = "ABCDE";
and i want to seperate them to 3 parts
(like part 1 = A, part 2 = B, part 3 = C..., part 5 = E)
,give a name to each of them
part 1(A) = Apple
part 2(B) = Orange
part 3(C) = Ice-cream
part 3(D) = Water
part 5(E) = Cow
then the finally output is like
Output : You choose Apple, Orange, Ice-cream, Water, Cow
or like this
$result = "ACE";
Output : You choose Apple, Ice-cream, Cow
i have tried using array
$result = "ABCDE";
$showing = array(A => 'Apple , ', B => 'Orange , ', C => 'Ice-cream , ',
D => 'Water , ', E => 'Cow , ');
echo $showing[$result];
but i got nothing while output, seems array is not working in fixed string.
i want to know how to do it
For one line magic:
echo implode('',array_intersect_key($showing,array_flip(str_split($result))));
You can use the function str_split to split the string into individual letters, which can later be used as keys of your associative array.
Also you don't need to add comma at the end of each string. Instead you can use the implode function to join your values:
$input = "ABCDE";
$showing = array('A' => 'Apple', 'B' => 'Orange', 'C' => 'Ice-cream',
'D' => 'Water', 'E' => 'Cow');
$key_arr = str_split($input);
$val_arr = array();
foreach($key_arr as $key) {
$val_arr[] = $showing[$key];
}
echo "You choose ".implode(',',$val_arr)."\n";
You can access characters from a string similar to elements in an array, like this:
$string = "ABCDE";
echo $string[2]; // "C"
Technically, it's not really treating it like an array, it just uses a similar syntax.
You could use
$choices= array('A' => 'Apple', 'B' => 'Orange', 'C' => 'Ice-cream',
'D' => 'Water', 'E' => 'Cow');
$selected[] = array();
for ($i = 0, $len = strlen($result); $i < $len; $i++) {
$selected[] = $choices[$string[$i]];
}
echo "You have selected: " . implode(', ', $selected);
Although str_split, as others have suggested, would also work.