Return multiple value of array in PHP - php

$array = [
'H',
'E',
'L',
'L',
'O',
];
This is my array. I want to print this array like this :
H
HE
HEL
HELL
HELLO
I want to do this dynamically .
For example, write a function to receive the array and do this with the array. Any array is possible.

You can use nested for loops to print the pattern as follows:
$array = [
'H',
'E',
'L',
'L',
'O',
];
echo printPattern($array);
function printPattern($array){
$ret = '';
for($i = 0; $i < count($array); $i++){
$str = '';
for($j = 0; $j < $i+1; $j++){
$str .= $array[$j];
}
$ret .= $str.'<br>';
}
return $ret;
}

Convert the array to a string, then iterate over the length of the string (either count the array or use strlen(), they'll be the same) and use substr() to get the given length, which will be the same as the number of the iteration.
$array = [
'H',
'E',
'L',
'L',
'O',
];
$string = implode("", $array);
for ($i = 0; $i <= count($array); $i++) {
echo substr($string, 0, $i)."\n";
}
Live demo at https://3v4l.org/ibXpK

Related

How to start looping through an array at a different index and finishing the entire array

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

Create pairs with 2 array, so that there is no repeated pairs?

I'm trying to create a script to create pairs from 2 different arrays. For example I have two array given below:
<?php
//Array 1
$arr1 = array('A', 'B', 'C', 'D');
//Array 2
$arr2 = array('X', 'Y', 'Z');
And I need output in such a manner so that it match with each element and didn't repeat pair and sequence also. Here is expected output:
$output = array(
0 => array('A', 'X'),
1 => array('B', 'Y'),
2 => array('C', 'Z'),
3 => array('D', 'X'),
4 => array('A', 'Y'),
5 => array('B', 'Z'),
6 => array('C', 'X'),
7 => array('D', 'Y'),
8 => array('A', 'Z'),
9 => array('B', 'X'),
10 => array('C', 'Y'),
11 => array('D', 'Z')
)
**Note: 2 arrays can differ with number of count and values.
This is Cartesian Product. Could be achieved with
//Array 1
$arr1 = array('A', 'B', 'C', 'D');
//Array 2
$arr2 = array('X', 'Y', 'Z');
$output = array();
foreach($arr1 as $i1){
foreach ($arr2 as $i2) {
$output[] = array($i1, $i2);
}
}
echo json_encode($output);
If you want the output to be in the same order as you have mentioned above, following should do that.
$newoutput = array();
$x = 0;
$y = 0;
for($i = 1; $i <= (count($arr1) * count($arr2)); $i++){
$newoutput[] = array($arr1[($x % count($arr1))], $arr2[($y % count($arr2))]);
$x++;
$y++;
}
echo "<br />", json_encode($newoutput);
Output however, is a different order of the same output as previous.
EDIT
The second works only when (count($arrX) % count($arrY)) > 0.
I don't think there is a built in support for that.
You need to loop the arrays nested and build a result array.
$arr1 = array('A', 'B', 'C', 'D');
$arr2 = array('X', 'Y', 'Z');
foreach($arr1 as $item1){
foreach($arr2 as $item2){
$res[] = [$item1, $item2];
}
}
var_dump($res);
https://3v4l.org/CdE8Q
Try This out (This will sort out the same pair if found):
//Array 1
$arr1 = array('A', 'B', 'C', 'D', 'A', 'E'); // Same element will be sort out in pair
//Array 2
$arr2 = array('X', 'Y', 'Z' , 'X', 'Y', 'X'); // Same element will be sort out in pair
$output = array();
$used_pair = array(); // Keeping used pair
$i = 1;
foreach ($arr1 as $each1) {
foreach ($arr2 as $each2) {
if (!in_array($each1.$each2, $used_pair)) {
$output[] = array($each1, $each2);
$used_pair[] = $each1 . $each2;
}
}
}
print_r($used_pair); // array with pair string
print_r($output); // array with pair array
this is an example that ouputs unique values in the same order :
online eval : https://3v4l.org/H2pad
<?php
function cartesian(array $x,array $y): array
{
$result = [];
$size = count($x) * count($y);
$posX = 0;
$posY = 0;
for($i = 0; $i < $size; $i++) {
if (!isset($x[$posX])) {
$posX = 0;
} elseif(!isset($y[$posY])) {
$posY = 0;
}
$result[] = [$x[$posX],$y[$posY]];
$posX++; $posY++;
}
return $result;
}
$x = array('A', 'B', 'C', 'D');
$y = array('X', 'Y', 'Z');
print_r(cartesian($x,$y));
( tbh, it took me a lot of rubber duck debugging )

Move 7 random elements from one array to another

In a word game with 2 players I would like to give 7 random letters to each player in the PHP 5.3 function creating a new game:
$LETTERS = 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' );
$NUMBERS = array( 2, 10, 3, 5, 3, 5, 9, 2, 2, 8, 4, 6, 4, 5, 8, 10, 6, 6, 6, 5, 3, 1, 2, 1, 2, 1, 1 );
function createGame($dbh, $uid) {
global $LETTERS, $NUMBERS;
$letters = array();
$letters1 = array();
$letters2 = array();
for ($i = 0; $i < count($LETTERS); $i++) {
$letter = $LETTERS[$i];
$number = $NUMBERS[$i];
for ($n = 0; $n < $number; $n++) {
array_push($letters, $letter);
}
}
for ($i = 0; $i < 7; $i++) {
/* TODO move random letter from $letters to $letter1 */
/* TODO move random letter from $letters to $letter2 */
}
$sth = $dbh->prepare('insert into games (player1, stamp1, stamp2, letters1, letters2, letters, board) values (?, unix_timestamp(now()), 0, ?, ?, ?, space(225))');
$sth->execute(array($uid, join('', $letters1), join('', $letters2), join('', $letters)));
return $dbh->lastInsertId();
}
I know that array_rand() can be used to select a random element from an array.
But how to use it here in a most effective way to move a letter from the $letters array?
UPDATE:
I've tried the following, but the first 7 letters are not removed from the beginning of the source array, why?
shuffle($letters);
$letters1 = array_slice($letters, 0, 7);
$letters2 = array_slice($letters, 0, 7);
I would shuffle the array of letters and remove the first element of the shuffeld array to get one random letter.
shuffle($letters); // Mix alle array elements
for ($i = 0; $i < 7; $i++) {
$letters1[] = array_shift($letters); // get first array element, removing it from $letters
$letters2[] = array_shift($letters); // get first array element, removing it from $letters
}
You can use array_diff:
$letters = array_diff($letters, $letter1);
$letters = array_diff($letters, $letter2);

php how to cut array and add other charactor to it

I have an array like :
Array
(
[0] => a
[1] => b
[2] => c
[3] => d
[4] => e
[5] => f
[6] => g
[7] => h
)
And I want add semicolon(;) every 3 index value and it's read from end of array that result is string like "ab;cde;fgh";
Here's a fun, and kind of obnoxious, one-liner:
$str = ltrim(strrev(chunk_split(implode(array_reverse($arr)), 3, ';')), ';');
Example:
$arr = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h');
$str = ltrim(strrev(chunk_split(implode(array_reverse($arr)), 3, ';')), ';');
echo $str; //ab;cde;fgh
// More sample output based on different input arrays:
$arr = array('a', 'b', 'c', 'd', 'e'); //ab;cde
$arr = array('a', 'b', 'c', 'd', 'e', 'f'); //abc;def
$arr = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'); //ab;cde;fgh;ijk
See demo
Its an odd way, but since you want it reversed you may need to use some function here:
$array = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h');
$array = array_reverse($array); // reverse it
$array = array_chunk($array, 3); // cut by threes
$string = '';
foreach ($array as $value) {
$string .= implode($value); // glue them
if(count($value) == 3) { // if still three, add a semi
$string .= ';';
}
}
$string = strrev($string); // then reverse them again
echo $string; // ab;cde;fgh
This works... there's a couple different ways to do this. This was the quickest way off the top of my head without using a second array.
$vars = array("a","b","c","d","e","f","g","h");
print_r(insert_char($vars));
function insert_char($Array, $Delimeter=";", $Count=3) {
for ($i = sizeOf($Array) - $Count; $i > 0; $i -= $Count)
array_splice($Array, $i, 0, $Delimeter);
return implode($Array);
}
Result
ab;cde;fgh
Here's my solution, although it feels inefficient it is pretty clear:
<?php
$myarr=Array('a','b','c','d','e','f','g','h');
$newarr=Array();
$arrsize = sizeof($myarr);
for ($x = 0, $i = 0; $x < $arrsize; $x++, $i++) {
$newarr[$i] = $myarr[$arrsize - $x - 1];
if (($arrsize - $x) % 3 == 0) {
$i++;
$newarr[$i] = ";";
}
}
$newarr = array_reverse($newarr);
print_r($newarr);
?>
Just traversing it from backward and joining the string in reverse too gives that result.
$vars = array("a","b","c","d","e","f","g");
$c = 0; $s = "";
for ($i = sizeof($vars)-1; $i >= 0; $i--)
{
$c++;
$s = $vars[$i].$s;
if ($c == 3) { $c = 0; $s = ";".$s; }
}
echo $s;

Keeping even numbered elements of an array?

Say I have an $input array, that contains something like this :
array
0 => string 'a' (length=1)
1 => string 'b' (length=1)
2 => string 'c' (length=1)
3 => string 'd' (length=1)
4 => string 'e' (length=1)
5 => string 'f' (length=1)
6 => string 'g' (length=1)
7 => string 'h' (length=1)
8 => string 'i' (length=1)
9 => string 'j' (length=1)
I want to get an $output array, that would contain this :
array
0 => string 'a' (length=1)
1 => string 'c' (length=1)
2 => string 'e' (length=1)
3 => string 'g' (length=1)
4 => string 'i' (length=1)
The $output array contains half the values that were in $input ; those that had even numbered keys in the input; the first one is kept, second one is not, third one is, and so one...
(Note: the keys are not preserved ; only the values are important)
How could I do that ? Keeping only one on two values of the array ?
I have already tried some ideas, and already have a couple different solutions :
First idea: iterate over the input array, and copy the interesting values to the output array:
$input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
$output = array();
$nbr = count($input);
for ($i = 0 ; $i < $nbr ; $i += 2) {
$output[] = $input[$i];
}
var_dump(array_values($output));
Second idea: iterate over the array, and unset what I don't want to keep:
$input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
$output = $input;
$nbr = count($input);
for ($i = 1 ; $i < $nbr ; $i += 2) {
unset($output[$i]);
}
var_dump(array_values($output));
Third idea: use a combinaison of array_flip, range, array_diff_key, ... :
$input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
$output = array();
$keys_to_exclude = array_flip(range(1, count($input)-1, 2));
$output = array_diff_key($input, $keys_to_exclude);
var_dump(array_values($output));
Fourth idea: about the same thing, but with array_intersect_key:
$input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
$output = array();
$keys_to_include = array_flip(range(0, count($input)-1, 2));
$output = array_intersect_key($input, $keys_to_include);
var_dump(array_values($output));
Any other idea ? Even / particularly if it sounds kinda hacky or anything ?
My goal is not to get the most efficient nor simple syntax ; it's just for fun and because I am curious, actually ^^
If the title is not using the right words to describe what I want, don't hesitate to tell ; or edit it :-)
<?php
$x = range('a', 'f');
$x = array_map('array_shift',
array_chunk($x, 2)
);
var_dump($x);
or another one
<?php
class ArrayEvenIterator extends ArrayIterator {
public function next() {
parent::next();
return parent::next();
}
}
$x = range('a', 'f');
$x = iterator_to_array(new ArrayEvenIterator( $x ), false);
var_dump($x);
or with a php 5.3 closure (which isn't better than global in this case ;-) )
<?php
$x = range('a', 'f');
$x = array_filter( $x, function($e) use(&$c) { return 0===$c++%2; });
var_dump($x);
Assuming numeric keys:
foreach ($array as $key => $value) {
if ($key % 2 != 0) {
unset($array[$key]);
}
}
EDIT
Here goes my slightly more insane solution which keeps the index continuous without re-indexing. ;o)
foreach ($array as $key => $value) {
if (!($key%2)) {
$array[$key/2] = $value;
}
}
$array = array_slice($array, 0, ceil(count($array)/2));
If you're using PHP 5.3 or later, or have the SPL extension installed (you will by default on PHP 5), you can use the FilterIterator and ArrayObject classes.
class EvenKeysFilter extends FilterIterator
{
private function iseven($keyval)
{
return (($keyval % 2) == 0);
}
public function accept()
{
$keyval = $this->getInnerIterator()->key();
return ($this->iseven($keyval));
}
}
$input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
$inputobj = new ArrayObject($input);
$evenFilterIter = new EvenKeysFilter($inputobj->getIterator());
$output = iterator_to_array($evenFilterIter, false);
print_r($output);
(Props to VolkerK for pointing out iterator_to_array())
Which correctly outputs this:
Array
(
[0] => a
[1] => c
[2] => e
[3] => g
[4] => i
)
Not necessarily the most efficient method, but since you mentioned that wasn't necessarily a requirement...
flip, filter, then flip back.
<?php
function even($var)
{
return(!($var & 1));
}
$input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
$flipped = array_flip($input);
$filtered = array_filter($flipped, 'even');
$output = array_flip($filtered);
?>
I would invert the bitwise-odd check and either use array_filter() (and reindexing the result with array_values()) or use a classic foreach() loop.
Code: (Demo)
$array = range('a', 'j');
var_export(
array_values(
array_filter(
$array,
function($k) {
return !($k & 1);
},
ARRAY_FILTER_USE_KEY
)
)
);
echo "\n---\n";
$result = [];
foreach ($array as $index => $value) {
if (!($index & 1)) {
$result[] = $value;
}
}
var_export($result);
Output:
array (
0 => 'a',
1 => 'c',
2 => 'e',
3 => 'g',
4 => 'i',
)
---
array (
0 => 'a',
1 => 'c',
2 => 'e',
3 => 'g',
4 => 'i',
)
In my own projects, I prefer to keep global variable declarations to a minimum, so I'd use array_filter().
create a wrapper function
function getInput($i)
{
global $input;
return $input[$i*2];
}
The smallest and most efficient I guess.
function dropHalf($a){
$f=0;
foreach($a as $k=>$v)
if($f = ! $f)
unset($a[$k]);
return $a;
}
That's the smallest version I could think off.

Categories