Related
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 )
Say I have an array of strings like this:
$in_arr = ['a', 'a', 'b', 'b', 'a', 'b', 'b', 'a', 'a', 'b'];
I would like an efficient way to merge all a's into a single value but leave the b's untouched so the result will be:
['a', 'b', 'b', 'a', 'b', 'b', 'a', 'b']
This is a possible solution:
<?php
define('ASPECT', 'a');
$input = ['a', 'a', 'b', 'b', 'a', 'b', 'b', 'a', 'a', 'b'];
$output = [];
array_walk($input, function($entry) use (&$output) {
if (($entry != ASPECT) || (end($output) != ASPECT)) {
$output[] = $entry;
}
});
print_r($output);
The output obviously is:
Array
(
[0] => a
[1] => b
[2] => b
[3] => a
[4] => b
[5] => b
[6] => a
[7] => b
)
With array_reduce:
$res = array_reduce($arr, function ($c, $i) {
if ( $i!='a' || end($c)!='a' )
$c[] = $i;
return $c;
}, []);
You could iterate through the list and only add strings to a new list if they're not your key string or if they are different from the previous string, something like this:
$in_arr = ['a', 'a', 'b', 'b', 'a', 'b', 'b', 'a', 'a', 'b'];
$new_arr = [];
$last = '';
$key = 'a';
foreach ($in_arr as $item) {
if ($key == $item and $item == $last) {
continue;
}
$last = $item;
array_push($new_arr, $item);
}
echo "[";
foreach( $new_arr as $value ){
echo $value.", ";
}
echo "]";
produces
[a, b, b, a, b, b, a, b, ]
Edit: PHP sandbox
You Require code :
<?php
$in_arr = array('a', 'a', 'b', 'b', 'a', 'b', 'b', 'a', 'a', 'b');
$last_temp = '';
for($i=0;$i<count($in_arr);$i++)
{
if($last_temp == $in_arr[$i] && $in_arr[$i]=='a')
{
unset($in_arr[$i]);
$in_arr = array_values($in_arr);
}
else
{
$last_temp = $in_arr[$i];
}
}
echo json_encode($in_arr);
Output :
["a","b","b","a","b","b","a","b"]
I am using Kody kreskowe - EAN-13 by Jacek Kowalski (http://jacekk.info) to generate EAN13 barcode and save it to image file. I would like generate barcode dynamically during the ordering process in Prestashop. Save that image on server and put it in new_order.html email template.
There is whole code: https://jacekk.info/skrypty/ean13.phps
I modified it lightly by change $_GET['kod'] to $kod_in and put $kod_in = 1234567891011 at start of file and imagepng($i, $new_filename); at the end
Everything works well (I see generated barcode and script create new image file and save it on server) when I enter directly to file ean13.php or if I run that code (directly in web browser):
$kod_in = 1234567891011;
include (dirname(__FILE__)."/ean13.php");
But when I try include the above code into order process, exactly in mailalerts.php, it does not display barcode and generate blank (white) image file. I think it has something to do with the fact that the generated barcode is not displayed on the screen, and then is saved.
Please help modify the code to generate the images even though they are not displayed on the screen.
At the end of the script replace this:
header('Content-type: image/gif');
imagegif($i);
With this:
$imageLocation = "where/you/want/to/save/your/file";
imagegif($i, $imageLocation);
Here is imagegif Documentation
You can use this library as a Class this way:
<?php
/***************************************************
* Kody kreskowe - EAN-13 *
***************************************************
* Ostatnia modyfikacja: 01.11.2012 *
* Autor: Jacek Kowalski (http://jacekk.info) *
* *
* Strona WWW: http://jacekk.info/scripts/barcodes *
* *
* Utwór rozprowadzany na licencji *
* http://creativecommons.org/licenses/by-nc/2.5/ *
***************************************************/
/* Kodowanie znaków UTF-8 */
class BarCode {
public $kol = array(
'0' => array('A', 'A', 'A', 'A', 'A', 'A'),
'1' => array('A', 'A', 'B', 'A', 'B', 'B'),
'2' => array('A', 'A', 'B', 'B', 'A', 'B'),
'3' => array('A', 'A', 'B', 'B', 'B', 'A'),
'4' => array('A', 'B', 'A', 'A', 'B', 'B'),
'5' => array('A', 'B', 'B', 'A', 'A', 'B'),
'6' => array('A', 'B', 'B', 'B', 'A', 'A'),
'7' => array('A', 'B', 'A', 'B', 'A', 'B'),
'8' => array('A', 'B', 'A', 'B', 'B', 'A'),
'9' => array('A', 'B', 'B', 'A', 'B', 'A')
);
public $code = array(
'start' => '101',
'lewa' => array(
'A' => array(
'0' => '0001101',
'1' => '0011001',
'2' => '0010011',
'3' => '0111101',
'4' => '0100011',
'5' => '0110001',
'6' => '0101111',
'7' => '0111011',
'8' => '0110111',
'9' => '0001011'
),
'B' => array(
'0' => '0100111',
'1' => '0110011',
'2' => '0011011',
'3' => '0100001',
'4' => '0011101',
'5' => '0111001',
'6' => '0000101',
'7' => '0010001',
'8' => '0001001',
'9' => '0010111'
)
),
'srodek' => '01010',
'prawa' => array(
'0' => '1110010',
'1' => '1100110',
'2' => '1101100',
'3' => '1000010',
'4' => '1011100',
'5' => '1001110',
'6' => '1010000',
'7' => '1000100',
'8' => '1001000',
'9' => '1110100'
),
'stop' => '101'
);
public $b;
public function __construct($barcode) {
$len = strlen($barcode);
if(trim($barcode, '0123456789')!='' OR ($len!=12 AND $len!=13)) {
echo 'Znaki inne niż cyfry lub błędna długość ('.$len.')';
die();
}
$kod = str_split(substr($barcode, 0, 12));
$now = 1;
$sum = 0;
foreach($kod as $val) {
if($now==1) {
$sum += $val;
$now = 3;
}
else
{
$sum += $val*3;
$now = 1;
}
}
$sum = 10-($sum%10);
if($sum==10) $sum = 0;
if($len==12) {
$barcode .= $sum;
}
elseif(substr($barcode, -1)!=$sum) {
echo 'Błędna suma kontrolna '.$sum;
die();
}
unset($len, $kod, $now, $sum);
$sys = substr($barcode, 0, 1);
$lewa = substr($barcode, 1, 6);
$prawa = substr($barcode, 7);
$i = imagecreate(95, 40);
$w = imagecolorallocate($i, 255, 255, 255);
$this->b = imagecolorallocate($i, 0, 0, 0);
$this->print_code($this->code['start'].$this->gen_binary($lewa, 0, $sys).$this->code['srodek'].$this->gen_binary($prawa, 1, $sys).$this->code['stop'], $i);
imagegif($i, 'test.gif');
}
public function gen_binary($kod, $strona, $sys) {
$kod = str_split($kod);
$ret = '';
if($strona==0) {
foreach($kod as $key => $val) {
$ret .= $this->code['lewa'][$this->kol[$sys][$key]][$val];
}
}
else
{
foreach($kod as $val) {
$ret .= $this->code['prawa'][$val];
}
}
return $ret;
}
public function print_code($kod, $img) {
$now = 0;
$kod = str_split($kod);
foreach($kod as $val) {
if($val==1) {
imageline($img, $now, 0, $now, 40, $this->b);
$now++;
}
elseif($val==0) {
$now++;
}
}
}
}
You need to include it once at the top of your file before your class declaration:
include_once('path/to/BarCode.php');
Now instead of including the script to generate an image you'll have to create a new BarCode Object.
new BarCode('9780486425573');
Tested and working on my Prestashop 1.6.
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;
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.