Combine arrays, but in a specific way - php

I have not even started the codeing process, because i cant figure out the logic.
I have 2 arrays
$urls = array(0 => url1,
1 => url2,
2 => url3,
3 => url4);
$domains = array(0 => domain_a,
1 => domain_b,
2 => domain_c,
3 => domain_d);
i need and output like
[0] => array ( [domain] => domain_a
[urls] => array (
[0] => url2,
[1] => url4 ))
[1] => array ( [domain] => domain_b
[urls] => array (
[0] => url1,
[1] => url3 ))
[2] => array ( [domain] => domain_c
[urls] => array (
[0] => url1,
[1] => url4 ))
[3] => array ( [domain] => domain_d
[urls] => array (
[0] => url2,
[1] => url3 ))
Until all domains has bin packed with 2 urls. The packing of the urls must be random, but the use of each url must be the same, or close to the same.

If you ever can't do something, the best thing is to break it down into chunks.
The answer to your question is likely to create a copy of the array of urls, and loop through the domains adding two of these urls each time — at random. When you do so, remove the item from the array. If the copy of urls is empty, create a fresh copy.
// The output
$output = [];
// The selection of arrays. We can populate this later...
$selection = [];
// Loop through every domain...
foreach($domains as $domain){
// Create the template that you want in the output. So far this is nearly the whole way there, we just need to add the random urls
$newItem = [
"domain" => $domain,
"urls" => []
];
// You want 2 urls per domain, so we'll do a for loop twice. ($i < 2)
for($i = 0; $i < 2; $i++){
// If the $selection list is empty (it will be at the start of the function, and also in your example on domain_c make a simple copy of the urls)
if(count($selection) <= 0){
$selection = $urls;
}
// Now find a random key for an item in the array
$randomKey = array_rand($selection);
// Push the item into the array of urls
$newItem["urls"][] = $selection[$randomKey];
// remove it from the array of items to pick from (so it won't come up again until you create a new copy, after all the others are used)
unset($selection[$randomKey]);
}
// Add this to the output:
$output[] = $newItem;
}

Using shuffle() and a simple foreach should be enough to do the job. For an arbitrary number of domains to be distributed randomly onto another number of urls use the following script:
$url=array('url1','url2','url3','url4');
$dom=array('dom_a','dom_b','dom_c');
$urls=$url; // copy the array
shuffle($urls); // shuffle the domains
$ul=count($urls); // length of $url
$dl=count($dom); // length of $dom
foreach ($urls as $k => $u)
$res[$k]=["domain"=>$dom[$k%$dl], "urls"=>[$u,$urls[($k+1)%$ul]]];
print_r($res);
See DEMO here: https://rextester.com/PFS53297

This code provides for a different number of domains and URLs in the input:
$urls = array(
0 => 'url1',
1 => 'url2',
2 => 'url3',
3 => 'url4'
);
$domains = array(
0 => 'domain_a',
1 => 'domain_b',
2 => 'domain_c',
3 => 'domain_d'
);
$result = [];
foreach ($domains as $domain) {
$urlsBucket = [];
while (count($urlsBucket) < 2) { // We need only 2 URLs
$randomUrl = $urls[array_rand($urls)]; // Get random URL
if (in_array($randomUrl, $urlsBucket)) { // To avoid duplication in the URL list
continue;
}
$urlsBucket[] = $randomUrl;
}
$result[] = [
'domain' => $domain,
'urls' => $urlsBucket
];
}
var_dump($result);
Output:
array(4) {
[0]=>
array(2) {
["domain"]=>
string(8) "domain_a"
["urls"]=>
array(2) {
[0]=>
string(4) "url2"
[1]=>
string(4) "url1"
}
}
[1]=>
array(2) {
["domain"]=>
string(8) "domain_b"
["urls"]=>
array(2) {
[0]=>
string(4) "url2"
[1]=>
string(4) "url4"
}
}
[2]=>
array(2) {
["domain"]=>
string(8) "domain_c"
["urls"]=>
array(2) {
[0]=>
string(4) "url3"
[1]=>
string(4) "url1"
}
}
[3]=>
array(2) {
["domain"]=>
string(8) "domain_d"
["urls"]=>
array(2) {
[0]=>
string(4) "url1"
[1]=>
string(4) "url2"
}
}
}
DEMO: https://paiza.io/projects/c9rXHcprCgsWnUlJ9UNNsg?language=php

Related

PHP Multidimensional array - Remove part duplicates and add up

I have a multidimensional array like so:
array(4) {
[0] => array(2) {
[0] => string(15)
"One"
[1] => string(5)
"11:31"
}
[1] => array(2) {
[0] => string(4)
"Two"
[1] => string(5)
"11:31"
}
[2] => array(2) {
[0] => string(15)
"Three"
[1] => string(5)
"11:31"
}
[3] => array(2) {
[0] => string(4)
"One"
[1] => string(5)
"11:31"
}
}
I am trying to get the ones with the first value removed but added up together. So it would end up like so:
array(3) {
[0] => array(2) {
[0] => string(15)
"One"
[1] => string(5)
"22:62"
}
[1] => array(2) {
[0] => string(4)
"Two"
[1] => string(5)
"11:31"
}
[2] => array(2) {
[0] => string(15)
"Three"
[1] => string(5)
"11:31"
}
}
Note the last 'One' has been removed and the second value in the array has been added up there from two 11:31's to 22:62. I hope that makes sense.
Is there something or a specific function I should look at to push me in the right direction? Any help much appreciated.
This is not just a straight up removing duplicates from what I can tell, as none are ever exactly the same although the second values are in this example, they won't be in live data.
You could make a loop and group elements into a new array using key [0]. It the key doesn't exists in the new array, simply add the new array. Otherwise, you could parse the existing value to add the new value:
$array = [
["One", "11:31"],
["Two", "11:31"],
["Three", "11:31"],
["One", "11:31"],
];
$out = [];
foreach ($array as $item) {
// if $item[0] is not an existing key,
if (!isset($out[$item[0]])) {
// add $item as-is
$out[$item[0]] = $item;
} else {
// parse current time
list($h1, $m1) = explode(':', $item[1]);
$m1 += $h1 * 60;
// parse existing time
list($h2, $m2) = explode(':', $out[$item[0]][1]);
$m1 += $m2 + $h2 * 60;
// compute new time
$h = floor($m1 / 60);
$out[$item[0]][1] = sprintf("%02d:%02d", $h, $m1-$h*60);
}
}
// array_values removes 'named' keys.
print_r(array_values($out));
Output (condensed):
Array
(
[0] => Array ([0] => One [1] => 23:02)
[1] => Array ([0] => Two [1] => 11:31)
[2] => Array ([0] => Three [1] => 11:31)
)

How to create a new key name and combine values in array with PHP?

I have 2 PHP arrays that I need to combine values together.
First Array
array(2) {
[0]=>
array(1) {
["id"]=>
string(1) "1"
}
[1]=>
array(1) {
["id"]=>
string(2) "40"
}
}
Second Array
array(2) {
[0]=>
string(4) "1008"
[1]=>
string(1) "4"
}
Output desired
array(2) {
[0]=>
array(1) {
["id"]=>
string(1) "1",
["count"]=>
string(1) "1008"
}
[1]=>
array(1) {
["id"]=>
string(2) "40",
["count"]=>
string(1) "4"
}
}
As you can see I need to add a new key name (count) to my second array and combine values to my first array.
What can I do to output this array combined?
Try something like the following. The idea is to iterate on the first array and for each array index add a new key "count" that holds the value contained on the same index of the second array.
$array1 = [];
$array2 = [];
for ($i = 0; $i < count($array1); $i++) {
$array1[$i]['count'] = $array2[$i];
}
you can do it like this
$arr1=[["id"=>1],["id"=>40]];
$arr2=[1008,4];
for($i=0;$i<count($arr2);$i++){
$arr1[$i]["count"] = $arr2[$i];
}
Live demo : https://eval.in/904266
output is
Array
(
[0] => Array
(
[id] => 1
[count] => 1008
)
[1] => Array
(
[id] => 40
[count] => 4
)
)
Another functional approach (this won't mutate/change the initial arrays):
$arr1 = [['id'=> "1"], ['id'=> "40"]];
$arr2 = ["1008", "4"];
$result = array_map(function($a){
return array_combine(['id', 'count'], $a);
}, array_map(null, array_column($arr1, 'id'), $arr2));
print_r($result);
The output:
Array
(
[0] => Array
(
[id] => 1
[count] => 1008
)
[1] => Array
(
[id] => 40
[count] => 4
)
)
Or another approach with recursion:
$arr1=[["id"=>1],["id"=>40]];
$arr2=[1008,4];
foreach ($arr1 as $key=>$value) {
$result[] = array_merge_recursive($arr1[$key], array ("count" => $arr2[$key]));
}
print_r($result);
And output:
Array
(
[0] => Array
(
[id] => 1
[count] => 1008
)
[1] => Array
(
[id] => 40
[count] => 4
)
)

Move array in array to parent array php

Is there a specific function to move array which is in array to the parent array as key or value.
array(5) { [0]=> array(1) { [0]=> string(2) "id" } [1]=> array(1) { [0]=> string(7)
"buydate" } [2]=> array(1) { [0]=> string(6) "expire" } [3]=> array(1) { [0]=> string(6)
"planid" } [4]=> array(1) { [0]=> string(5) "buyer" } }
Result I would like to get is:
array() { [0] => 'id', [1] => 'buydate' etc. }
Or
array('id', 'buydate' etc.. )
Is it possible to achieve without foreach ?
array_map() is extremely powerful and should do the trick:
$array = ... ; // your initial array
$flattened_array = array_map(function($item) {
return $item[0];
}, $array);
If you want to flatten the desired array, and use foreach you can do it this way.
Consider this example:
// Sample data:
$values = array(
0 => array(
0 => 'id',
),
1 => array(
0 => 'buydate',
),
2 => array(
0 => 'expire',
),
3 => array(
0 => 'planid',
),
4 => array(
0 => 'buyer',
),
);
$new_values = array();
foreach($values as $key => $value) {
$new_values[] = $value[0];
}
print_r($new_values);
Sample Output:
Array
(
[0] => id
[1] => buydate
[2] => expire
[3] => planid
[4] => buyer
)
Or alternatively, you can you the iterator. Consider this example:
$new_values = array();
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($values));
foreach($iterator as $value) {
$new_values[] = $value;
}
It should gave you the same output.

Changing \n into ARRAY values within another ARRAY

I have this ARRAY sent from a FORM
Array
(
[0] => one
two
three
[1] => hello
how
are
)
Since the values are sent via textarea from a form, it has line breakers, so I want to make change every into a array field like so:
Array
(
[0] => Array
(
[0] => one
[1] => two
[2] => three
)
[1] => Array
(
[0] => hello
[1] => how
[2] => are
)
)
This is what I have so far:
foreach ($array as &$valor) {
foreach(preg_split("/((\r?\n)|(\r\n?))/", $valor) as $line){
$arraynew[] = $line;
}
}
But I get this result
Array
(
[0] => one
[1] => two
[2] => three
[3] => hello
[4] => how
[5] => are
)
What am I doing wrong? :(
For each key in the POST array, pop a value onto the final array, with it's values containing an array whoses values represent each line in value of the POST array.
<?php
$data = array(
0 => "one\ntwo\nthree",
1 => "hello\nhow\nare"
);
$final = array();
for($i = 0; $i < count($data); $i++) {
$row = preg_split('/\n/', $data[$i]);
if(is_array($row)) {
for($j = 0; $j < count($row); $j++) {
$final[$i][] = $row[$j];
}
}
}
var_dump($final);
array(2) {
[0] =>
array(3) {
[0] =>
string(3) "one"
[1] =>
string(3) "two"
[2] =>
string(5) "three"
}
[1] =>
array(3) {
[0] =>
string(5) "hello"
[1] =>
string(3) "how"
[2] =>
string(3) "are"
}
}
DEMO
Well, you're really working too hard.
array_map(function($e) { return explode("\n", $e); }, $orig_array);
is all you need. You could use preg_split if you really want, but explode is enough.
You can simply do this
$array=array("one\ntwo\nthree","hello\nhow\nare");
$arraynew=array();
foreach ($array as &$valor) {
$arraynewtemp=array();
foreach(preg_split("/((\r?\n)|(\r\n?))/", $valor) as $line){
$arraynewtemp[] = $line;
}
array_push($arraynew,$arraynewtemp);
}
var_dump($arraynew);
Will output
array(2) {
[0]=>
array(3) {
[0]=>
string(3) "one"
[1]=>
string(3) "two"
[2]=>
string(5) "three"
}
[1]=>
array(3) {
[0]=>
string(5) "hello"
[1]=>
string(3) "how"
[2]=>
string(3) "are"
}
}
This should works

How to get rid of duplicate values from multidimensional array

I want to remove duplicate values from multi-dim array, I tried all the possible solutions which is already described but for me, is not working, can anyone please correct it?
Here's my Array:
Array (
[0] => Array (
[0] => element_10
[1] => block_1
[2] => element_4
[3] => element_1
[4] => element_3
)
[1] => Array (
[0] => block_1
[1] => block_2
[2] => element_8
[3] => element_10
[4] => element_12
[5] => element_14
[6] => element_4
[7] => element_2
[8] => element_3
[9] => element_9
[10] => element_13
[11] => element_7
)
)
Where I want the array in this format:
Array (
[0] => Array (
[0] => element_10
[1] => block_1
[2] => element_4
[3] => element_1
[4] => element_3
)
[1] => Array (
[1] => block_2
[2] => element_8
[4] => element_12
[5] => element_14
[7] => element_2
[9] => element_9
[10] => element_13
[11] => element_7
)
)
Ican setup the key indexes later.
I tried:
function multi_unique($array) {
foreach ($array as $k=>$na)
$new[$k] = serialize($na);
$uniq = array_unique($new);
foreach($uniq as $k=>$ser)
$new1[$k] = unserialize($ser);
return ($new1);
}
No Luck, then I tried:
function array_unique_multidimensional($input)
{
$serialized = array_map('serialize', $input);
$unique = array_unique($serialized);
return array_intersect_key($input, $unique);
}
Still same array returning.
I tried this method too:
function super_unique($array)
{
$result = array_map("unserialize", array_unique(array_map("serialize", $array)));
foreach ($result as $key => $value)
{
if ( is_array($value) )
{
$result[$key] = self::super_unique($value);
}
}
return $result;
}
Please help me, I know it's pretty simple I don't know where I'm losing?
Thanks,
You need to iterate over your list of input arrays. For each value in that array, you need to see if you've previously encountered it, so you'll have to keep a super-set of all values across all arrays, which you gradually append to. If a value already exists in the super-set array, you can remove it, otherwise you can append it.
function multi_unique($arrays) {
$all_values = array();
foreach ($arrays as &$array) {
foreach ($array as $index => $value) {
if (in_array($value, $all_values)) {
// We've seen this value previously
unset($array[$index]);
} else {
// First time we've seen this value, let it pass but record it
$all_values[] = $value;
}
}
}
return $arrays;
}
$values = array (
array ( 'element_10', 'block_1', 'element_4', 'element_1', 'element_3',) ,
array ( 'block_1', 'block_2', 'element_8', 'element_10', 'element_12', 'element_14', 'element_4', 'element_2', 'element_3', 'element_9', 'element_13', 'element_7',)
);
var_dump(multi_unique($values));
Output:
array(2) {
[0]=>
array(5) {
[0]=>
string(10) "element_10"
[1]=>
string(7) "block_1"
[2]=>
string(9) "element_4"
[3]=>
string(9) "element_1"
[4]=>
string(9) "element_3"
}
[1]=>
array(8) {
[1]=>
string(7) "block_2"
[2]=>
string(9) "element_8"
[4]=>
string(10) "element_12"
[5]=>
string(10) "element_14"
[7]=>
string(9) "element_2"
[9]=>
string(9) "element_9"
[10]=>
string(10) "element_13"
[11]=>
string(9) "element_7"
}
}
If you just want to remove duplicates from the second entry of your array, use array_diff():
$array[1] = array_diff($array[1], $array[0]);
Iterate if you want to apply it to an arbitrary length.
Why are you using the serialize function.
Use array_diff instead.
A simple would be.
$orginal = array(array(values), array(values), ...);
$copy = $original;
foreach($original as $k => $subArray) {
$tmpCopy = $copy;
unset($tmpCopy[$k]);
unshift($tmpCopy, $subArray);
$tmpCopy = array_values($tmpCopy);
$original[$k] = call_user_func_array('array_diff', $tmpCopy);
}
This works for a two dimensions array.
Hope it helps.

Categories