How to output different values from an array - php

I have a problem with my code. what I want to do is to delete an item from the array when it has been called meaning that, I want every output to be different. I want to use it to rotate proxy and there are over 150 proxies in the array. Here's an example of my code.
for ( $i = 1; $i < 2; $i++ )
{
// If the array_history is empty, re-populate it.
if (empty($array_history))
$array_history = $array;
// Select a random key.
$key = array_rand($array_history, 1);
// Save the record in $selected.
$selected = $array_history[$key];
// Remove the key/pair from the array.
unset($array_history[$key]);
// Echo the selected value.
echo $selected;
}
How can I do this or is a for loop not suitable for this? thanks in advance.

What you want to do is spread access over 150 proxies. In this case, it is not really necessary to do it randomly. You can just go through the array.
<?php
$array = [0, 1, 2, 3, 4, 5, 6];
for ( $i = 1; $i < 20; $i++ )
{
echo getNext($array) . '<br>';
}
function getNext (&$array) {
$e = next($array); // Every time next element is selected. Each output is different.
if ($e)
return $e;
else
return reset($array);
}
?>

This seems like a good application for a generator. This one takes an array of proxy addresses and loops over the array in random order, shuffling the array each time it starts the loop again.
function get_proxy($proxies) {
$i = 0;
$len = count($proxies);
while (true) {
if ($i == 0) shuffle($proxies);
yield $proxies[$i];
$i = ($i + 1) % $len;
}
}
To use this, you would do something like this:
$proxies = array('10.0.0.4', '192.168.0.1', '10.1.0.1');
$i = 0;
foreach (get_proxy($proxies) as $proxy) {
echo "$proxy\n";
$i++;
// stop otherwise infinite loop
if ($i == 9) break;
}
Note that since the generator has an infinite loop in it, the external foreach loop will also be infinite, and so needs a way to break out (I've used a simple counter in this case).
Sample output for the above code:
10.1.0.1
10.0.0.4
192.168.0.1
192.168.0.1
10.1.0.1
10.0.0.4
10.1.0.1
192.168.0.1
10.0.0.4
Demo on 3v4l.org
If a generator doesn't suit your code structure, you could use a function with static variables to return a new proxy on each call:
$proxies = array('10.0.0.4', '192.168.0.1', '10.1.0.1');
function get_proxy($proxies) {
static $i = 0, $keys;
if (!isset($keys)) $keys = array_keys($proxies);
if ($i == 0) shuffle($keys);
$proxy = $proxies[$keys[$i]];
$i = ($i + 1) % count($keys);
return $proxy;
}
for ($i= 0; $i < 9; $i++) {
echo get_proxy($proxies) . "\n";
}
Sample output for this code:
10.1.0.1
10.0.0.4
192.168.0.1
192.168.0.1
10.1.0.1
10.0.0.4
10.0.0.4
192.168.0.1
10.1.0.1
Demo on 3v4l.org

When you define an array in php such as
<?php
$alphabet = array(a, b, c)
?>
Your trying to look for the elements in the array. The element list always starts at a count of 0. So to call individual elements count from left to right starting at 0.
<?php
#a
echo $alphabet[0];
#b
echo $alphabet[1];
#c
echo $alphabet[2];
?>
The above section should yield a result of abc because there are no breaks.
For loops are really handy for going through the entire array and running checks, error analysis or even math as examples.

I've changed tho cede slightly, to me it reads as code that will take a selection of items, pick one at random, discard the item, and then pick again until none are left. If there are none left, copy the original array and start again.
Currently your code loops once. I've extended the loop to 4 iteratons here. And upon each random selection, am storing that random key in a history array. You can then refer to that history later in your code.
<?php
$array =
[
'beatle' => 'John',
'stone' => 'Mick',
'floyd' => 'Syd'
];
for ($history = [], $i = 1; $i < 5; $i++)
{
if (empty($buffer))
$buffer = $array;
$key = array_rand($buffer, 1);
$history[] = $key;
echo $buffer[$key], "\n";
unset($buffer[$key]);
}
var_export($history);
Example output:
Syd
Mick
John
Syd
array (
0 => 'floyd',
1 => 'stone',
2 => 'beatle',
3 => 'floyd',
)
Referring to the history array above:
echo $array[$history[3]];
Would output Syd.
Adapting and encapsulating the above in a class. This will do the same (but not store the history of picks), taking an item from an array at random and remove until there are no more items in the array, and then replenish the list and so on:
class RandomProxies
{
const PROXIES =
[
'proxy1' => 'foo.example.com',
'proxy2' => 'bar.example.com',
'proxy3' => 'baz.example.com',
];
private $buffer;
public function getProxy() {
if (empty($this->buffer))
$this->buffer = self::PROXIES;
$key = array_rand($this->buffer);
$proxy = self::PROXIES[$key];
unset($this->buffer[$key]);
return $proxy;
}
}
$randomiser = new RandomProxies;
foreach(range(1,4) as $n) {
echo $randomiser->getProxy(), "\n";
}
Example output:
foo.example.com
baz.example.com
bar.example.com
foo.example.com

Related

PHP replace every 2nd

<?php
$fact_BB = array("[start]", "[mid]", "[end]");
$fact_HTML = array("<tr><td class='FactsTableTDOne'><p>", "</p></td><td class='FactsTableTDTwo'><p>", "</p></td></tr>");
$str_Facts = str_replace($fact_BB, $fact_HTML, $row['facts']);
echo $str_Facts;
?>
Is it possible to switch between 2 $fact_HTML?
1. $fact_HTMLone = "code";
2. $fact_HTMLtwo = "code";
3. $fact_HTMLone = "code";
4. $fact_HTMLtwo = "code";
5. $fact_HTMLone = "code";
etc. etc.
Sure. With $fact_HTML[0], $fact_HTML[1], $fact_HTML[n] etc. you can access your $fact_HTML array. Using modulo of 2 you can always access every 2nd (or first and second) elements of the array.
To check if the element is even or odd you can use:
if ($n % 2 == 0) {
//even element
} else {
//odd element
}
Also you can use Modulo 2 ($n % 2) as n to iterate through the array in the same way. You can also combine both variants.
$count = 10; //number of facts
for ($n = 0; $n < $count; $n++) {
$fact_HTML[$n % 2] = $fact;
}
What you want to achieve is a replace of some strings. I'd suggest a solution like this:
<?php
$str_Facts = $row['facts'];
$replacements = array( "[start]" => "<tr><td class='FactsTableTDOne'><p>",
"[mid]" => "</p></td><td class='FactsTableTDTwo'><p>",
"[end]" => "</p></td></tr>" );
foreach ($replacements as $repkey => $repval) {
$str_Facts = str_replace($repkey,$repval,$str_Facts);
}
echo $str_Facts;
?>
If you want to go on with your approach, you'd loop through the arrays (you have to ensure that the both arrays have the same number of elements).
<?php
$str_Facts = $row['facts'];
for ($i=0;$i<count($fact_BB);$i++) {
//if you want to switch every uneven, do this:
if ($i%2!=0) continue;
$str_Facts = str_replace($fact_BB[$i],$fact_HTML[$i],$str_Facts);
}
echo $str_Facts;
?>

How to reverse an array in php WITHOUT using the array reverse method

I want to know how to reverse an array without using the array_reverse method. I have an array called reverse array which is the one i want to reverse. My code is below. could someone point out what i am doing wrong as I cannot find any example of reversing an array this way anywhere else. my code is below.
<?php
//Task 21 reverse array
$reverseArray = array(1, 2, 3, 4);
$tmpArray = array();
$arraySize = sizeof($reverseArray);
for($i<arraySize; $i=0; $i--){
echo $reverseArray($i);
}
?>
<?php
$array = array(1, 2, 3, 4);
$size = sizeof($array);
for($i=$size-1; $i>=0; $i--){
echo $array[$i];
}
?>
Below is the code to reverse an array, The goal here is to provide with an optimal solution. Compared to the approved solution above, my solution only iterates for half a length times. though it is O(n) times. It can make a solution little faster when dealing with huge arrays.
<?php
$ar = [34, 54, 92, 453];
$len=count($ar);
for($i=0;$i<$len/2;$i++){
$temp = $ar[$i];
$ar[$i] = $ar[$len-$i-1];
$ar[$len-$i-1] = $temp;
}
print_r($ar)
?>
The problem with your method is when you reach 0, it runs once more and index gets the value of -1.
$reverseArray = array(1, 2, 3, 4);
$arraySize = sizeof($reverseArray);
for($i=$arraySize-1; $i>=0; $i--){
echo $reverseArray[$i];
}
Here's another way in which I borrow the code from here and update it so that I eliminate having to use a $temp variable and instead take advantage of array destructuring, as follows:
<?php
/* Function to reverse
$arr from start to end*/
function reverseArray(&$arr, $start,
$end)
{
while ($start < $end)
{
[$arr[$start],$arr[$end]] = [$arr[$end],$arr[$start]];
$start++;
$end--;
}
}
$a = [1,2,3,4];
reverseArray($a,0,count($a)-1);
print_r($a);
See live code
One of the advantages of this technique is that the array $a is reversed in place so there is no necessity of creating a new array.
The following improves the code so that one need not pass more than one parameter to reverseArray(); as well as indicating that there is no return value:
/* Function to reverse
$arr from start to end*/
function reverseArray(&$arr, $start=0): void
{
$end = count($arr)-1;
while ($start < $end)
{
[$arr[$start],$arr[$end]] = [$arr[$end],$arr[$start]];
$start++;
$end--;
}
}
$a = [1,2,3,4];
reverseArray($a);
print_r($a);
See here
Note: this revision works in PHP 7.2-7.4.2
how to reverse a array without using any predefined functions in php..
i had a solution for this problem...
here is my solution........
<?php
// normal array --------
$myarray = [1,2,3,4,5,6,7,8,9];
//----------------
$arr = [];
for($i=9; $i > -1; $i--){
if(!$i==0){
$arr[]= $i;
}
}
print_r($arr);
//the out put is [9,8,7,6,5,4,3,2,1];
?>

Using an index twice in PHP

I am trying to use a for loop where it looks through an array and tries to make sure the same element is not used twice. For example, if $r or the random variable is assigned the number "3", my final array list will find the value associated with wordList[3] and add it. When the loop runs again, I don't want $r to use 3 again. Example output: 122234, where I would want something along the lines of 132456. Thanks in advance for the help.
for($i = 0; $i < $numWords; $i++){
$r = rand(0, $numWords);
$arrayTrack[$i] == $r;
$wordList[$r] = $finalArray[$i];
for($j = 0; $j <= $i; $j++){
if($arrayTrack[$j] == $r){
# Not sure what to do here. If $r is 9 once, I do not want it to be 9 again.
# I wrote this so that $r will never repeat itself
break;
}
}
Edited for clarity.
Pretty sure you are over complicating things. Try this, using array_rand():
$final_array = array();
$rand_keys = array_rand($wordList, $numWords);
foreach ($rand_keys as $key) {
$final_array[] = $wordList[$key];
}
If $numWords is 9, this will give you 9 random, unique elements from $wordList.
See demo
$range = range(0, $numWords - 1); // may be without -1, it depends..
shuffle($range);
for($i = 0; $i < $numWords; $i++) {
$r = array_pop($range);
$wordList[$r] = $finalArray[$i];
}
I do not know why you want it.. may be it is easier to shuffle($finalArray);??
So ideally "abcdefghi" in some random order.
$letters = str_split('abcdefghi');
shuffle($letters);
var_dump($letters);
ps: if you have hardcoded array $wordList and you want to take first $n elements of it and shuffle then (if this is not an associative array and you do not care about the keys)
$newArray = array_slice($wordList, 0, $n);
shuffle($newArray);
var_dump($newArray);
You can try array_rand and unset
For example:
$array = array('one','two','free','four','five');
$count = count($array);
for($i=0;$i<$count;$i++)
{
$b = array_rand($array);
echo $array[$b].'<br />';
unset($array[$b]);
}
after you have brought the data in the array, you purify and simultaneously removing the memory array
Ok... I have NO idea why you are trying to use so many variables with this.
I certainly, have no clue what you were using $arrayTrack for.
There is a very good chance I am mis-understanding all of this though.
<?php
$numWords=10;
$wordList=array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z');
$finalArray=array();
for ($i=0; $i<$numWords; $i++) {
start:
$r=rand(0,$numWords);
$wordChoice=$wordList[$r];
foreach ($finalArray as $word) {
if ($word==$wordChoice) goto start;
}
$finalArray[]=$wordChoice;
}
echo "Result: ".implode(',',$finalArray)."\n";

PHP: Shuffle array, so no value is like the correspondent one

There is an array with names, for example:
$donalds_nephews = array('Huey', 'Dewey', 'Louie');
array
(
[0] => Huey
[1] => Dewey
[2] => Louie
)
I want to shuffle this array, but ensure that no value of the original array has the same key as the shuffled one.
$donalds_nephews_shuffled = shuffle($donalds_nephews);
This could result in 6 possible permutations:
Huey, Dewey, Louie
Huey, Louie, Dewey
Dewey, Louie, Huey
Dewey, Huey, Louie
Louie, Dewey, Huey
Louie, Huey, Dewey
1st, 2nd, 4th and 5th must not be the result.
What's the best way to do so? It's for Secret Santa.
Shuffle the original array, then make a copy of it and shift all entries one over, then match the two back together to get your matches.
It's for Secret Santa.
Then start with a better algorithm. Currently you seem to be inferring that the key is a present giver and the value a present receiver (or vice versa). This then entails the additional check (and possible re-iteration of the shuffling) to ensure that nobody ends up giving a present to themselves.
But what if you just consider it as an ordered list of names, such that each entry gives to the next person on the list:
$victims=array('Huey', 'Dewey', 'Louie');
shuffle($victims);
$giver='';
foreach($victims as $receiver) {
if ($giver) print "$giver gives to $receiver\n";
$giver=$receiver;
}
$receiver=array_shift($victims);
print "$giver gives to $receiver\n";
just cause i need this for my secret santa :)
<?php
function compareArrays($original, $shuffled){
for($i = 0; $i < count($original); $i++ ){
if($original[$i] == $shuffled[$i]){
return false;
}
}
return true;
}
$donalds_nephews = array('Huey', 'Dewey', 'Louie','Igor','Stephan');
//avoid loops
for($j = 0; $j < 50; $j++){
$shuffled = $donalds_nephews;
shuffle($shuffled);
$good = compareArrays($donalds_nephews, $shuffled);
if($good) break;
}
if($good){
echo "here we go!\n";
foreach($shuffled as $k => $v){
echo "$k => $v \n";
}
}
else {
echo "try again \n";
}
?>
Don't make this complicated by trying to put all of this into one function.
Here's your pseudocode:
$givers = array( 'Huey', 'Dewey', 'Louie' );
$getters = $givers;
foreach ( $givers as $giver ) {
do {
pick a random $getter from $getters;
} until $getter <> $giver;
delete $getter from $getters;
print "$giver gives to $getter\n";
}
It is an old question, but you asked for the best way, so how about this?
function santaYates($array) {
$returnArray = array_values($array); // Cause we need a clean numeric array
$secure = false;
for($i = count($returnArray) - 1; $i > 0; $i--) {
$r = mt_rand(0, $i-1); //subtract 1 from $i to force a new place.
$tmp = $returnArray[$i];
$returnArray[$i] = $returnArray[$r];
$returnArray[$r] = $tmp;
}
return $returnArray;
}
It works very similar to the Fisher-Yates shuffle.
There is just one little difference:
We permit to use the same key, so every entry will get a new place (cause we substract 1 from $i when we do the randomize step).
Working Demo

PHP Array shuffle, keeping unique

this is my first php script and problem, I've searched hours with no conclusion other than looping a function" too many laterations". but it doesn't solve my problem I've never studied programming or what ever so I'm hoping that there is an educated person to fill me in on this:
I have an array that contains 120 elements; consists of duplicates eg:
myArray = [0]= item_1, [1] = item _1, [2] = item_2, [3] = item_3 ect..
Briefly I'm trying to make a flash php pokermachine but I need these items in the array to be shuffled BUT I do not want the duplicates to be next to each other after the shuffle but I need the duplicates to be still in the array
I can't do a loop function to check this because it will change the shuffle too many times which will effect the odds of the game: below is what I currently have:
/ * Removed the link here that is no longer available */
you may notice at times it will double up with 2 items in the same reel
Basically I created the virtual reel dynamically with php.ini file
these values are repeatedly pushed into an array($virtualreel) so the value may appear 10 times in the reel and another value will appear 5 times variating the odds. Then after I take a random slice() from the $virtualreel to display 3 vars from this reel and repeat the loop 4 more times for the other reels, also I only can shuffle once as I want the slice() to be from the same reels array order
I only shuffle every new spin not running loop functions to shuffle if I double up on a slice(array,3 items).
hope I've explained what I'm after well enough to give you guys an idea.
You can use this function:
<?php
function shuffleArray($myArray) {
$value_count = array_count_values($myArray);
foreach($value_count as $key=>$value) {
if ($value > count($myArray)/2) {
return false;
}
}
$last_value = $myArray[count($myArray) - 1];
unset($myArray[count($myArray) - 1]);
$shuffle = array();
$last = false;
while (count($myArray) > 0) {
$keys = array_keys($myArray);
$i = round(rand(0, count($keys) - 1));
while ($last === $myArray[$keys[$i]]) {
$i = round(rand(0, count($keys) - 1));
}
$shuffle[] = $myArray[$keys[$i]];
$last = $myArray[$keys[$i]];
unset($myArray[$keys[$i]]);
}
if ($last_value === $last) {
$i = 0;
foreach($shuffle as $key=>$value) {
if ($value !== $last_value) {
$i = $key;
break;
}
}
array_splice($shuffle, $i + 1, 0, $last_value);
} else {
$shuffle[] = $last_value;
}
return $shuffle;
}
print_r(shuffleArray(array(1,5,5,3,7,7)));
Why not just:
Edit :
$shuffled = array();
while(count($to_shuffle) > 0):
$i = rand(0, count($to_shuffle)-1);
$shuffled[] = $to_shuffle[$i];
array_splice($to_shuffle, $i, 1,null);
endwhile;
I think this is what you were expecting, if you don't mind not preserving the association between keys and values.

Categories