Making 2 Arrays Random in the same way with php - php

I'm new to the stackoverflow so feel free to delete this question if it's stupid:
The main purpose of doing this is to display a list of details on a page randomly everytime it refreshes, but the details are in different arrays, so i have 2 arrays which i have to randomize in the same way,
Example:
$Name[0]=John;
$Name[1]=Lucy;
$Name[2]=Mike;
$Age[0]=18;
$Age[1]=20;
$Age[2]=25;
after being randomize becomes :
$Name[2]=Mike;
$Name[0]=John;
$Name[1]=Lucy;
$Age[2]=25;
$Age[0]=18;
$Age[1]=20;
I tried using "->", For example:
$Array[0]->name = 'John';
$Array[0]->age = '18';
$Array[1]->name = 'Lucy';
$Array[1]->age = '20';
shuffle($Array);
but my teacher wasn't thrilled because the code was messy since there's alot of transfer (Details into the new array before the randomizing and new array back into details after randomizing). He wants me to do it only with the 2 arrays.

What you are doing, is sort of the right way of doing things. Look at it this way. What exactly are you trying to achieve? You want a set of data sorted randomly (ok, sorting is not the right word here, but you get it). Whenever you talk about any kind of reordering of data, we talk about changing the order that the elements appear in. Your element here is neither 'name', nor 'age'. Your element here is 'person'. So, your data list should be a list of 'person's, which you would reorder and not in two loosely-coupled arrays.
Anyways, if you absolutely MUST do it this way. This is what I suggest.
Let there be two arrays $A and $B. Let them both have N elements. What you do is, create an array $nums, which has elements from 0 to N-1 i.e.
$nums = array(0, 1, 2 ... N-1)
Now, shuffle the $sums array. So, let's say we have something like:
$num = (3, 4, 1, 2)
Ok, so we have created a mapping here,
$num[0] = 3
means that the 0th element is 3, which you can interpret as in the new array, the 0th element should be the 3rd element of the old array. To do this, run a simple loop:
for($i=0; $i<N; $i++) {
$A2[$i] = $A[$num[$i]];
$B2[$i] = $B[$num[$i]];
}
It is a slightly challenging task if you insist on this being an online solution (a solution that modifies the original data structure and not build a new one), but I'll leave that ask to you (think of swapping data elements according to the map we just created). Also, you could extend it easily to more than 2 arrays, or an array of arrays in case you're not sure how many arrays one has to deal with. Feel free to ask any question you might have...

You should use an associative array.
$people = array('John' => 18, 'Lucy' => 20, 'Mike' => 25);
return shuffle_assoc($people);
function shuffle_assoc( $array )
{
$keys = array_keys( $array );
shuffle( $keys );
return array_merge( array_flip( $keys ) , $array );
}

Related

Restructure 2d array so that column values become row values (transpose but preserve first level keys)

The situation is as follows. I have a parent array which looks like the following:
$parent = [
1 => ['test1', 'test2'],
2 => ['test1_1', 'test2_2'],
];
I would like to group the data by column.
Desired result:
[
1 => ['test1', 'test1_1'],
2 => ['test2', 'test2_2'],
]
1 parent array called parent contains 2 arrays inside. I want to combine these two so that they have the same values as stated above. So this would mean that the arrays should be combined based on index number.
Since I do not make use of string keys, how would I accomplish this? I believe that there is no build in function available for this situation.
I would imagine that I could start beginning to create a new array and use a for loop through the parent array.
I tried the array-combine function however, this is NOT displaying the results I want.
[
1 => ['test1' => 'test1_1', 'test2' => 'test2_2'
]
If you need to preserve those first level keys, you can re-apply them after tranposing.
Code: (Demo)
var_export(
array_combine(array_keys($parent), array_map(null, ...$parent))
);
Otherwise, you can just transpose and accept the re-indexed first level keys. Honestly, I can't see any good reason to preserve the first level keys because by transposing, you remove the initial association between first level keys and the row values.
Code: (Demo)
var_export(
array_map(null, ...$parent)
);
If these techniques do not suit your actual project data, then we will need a more realistic sample array to be provided in your question body.
Loop over the keys of the top-level array. Then use the current index of the iteration to get the corresponding columns of the nested arrays.
$result = [];
foreach (array_keys($parent) as $i => $k) {
$result[$k] = array_column($parent, $i);
}
DEMO
This assumes the number of rows is the same as the number of columns. It's not clear what you expect the result to be if that's not true.

How do you have an associate array element point to a normal array (and add to it)

I want to create an associate array, where the first element points to a (normal) of elements. The array would look something like is:
[Jim] => (23, 18, 20)
[Mary] => (57, 19, 26, 67, 103)
This example has two elements, and each of those has its first element indexed by a 'name' (associativley).
The second element of each of these two entries is an array. These are essentially ways to access other data structures and these elements can have a variable number of elements.
I am really struggling to get the syntax right.
Do I declare the overall array as (say, as it is in a class)
protected $names = [];
... then when I come to add a new name, do I add to the array as:
array_push($this->authors[$givenName], array());
[this seems to work]
... but how do I add elements to the array that [$givenName] now points to?
I have been struggling for a couple of days and can't find the right syntax.
Any help appreciated.
G
I'm not sure that your syntax is correct. Instead, try the following:
//checking if we've initialized the data for $givenName; if not, we initialize the array before inserting
if(!isset($this->authors[$givenName])) {
$this->authors[$givenName] = array();
}
//insert a value into $givenName's array
array_push($this->authors[$givenName], $some_val);
//result is $this->authors = array($givenName => array($some_val))

Check if item exists in multiple arrays

I have a function which returns an array:
This is the fucntion:
{
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$product_names=array();
foreach($items as $item => $values) {
$_product = $values['data']->post;
$product_names[]=$_product->post_title;
}
$allproductname=print_r($product_names, true);
return $allproductname;
}
The output of this function:
Array(
[0] => Social media campagne
[1] => Marketingcampagne
)
I also have 2 arrays named group1 and group2.
$group1=array("Social media campagne","Marketingcampagne");
$group2=array("SEO","Facebook marketing");
Now what i want to check is if both of the values of the function output belong in $group1 then i want it to print "both values belong in group1"
And if 1 value belongs in group1 and one value in group 2 then echo "1 value belongs in group1 and one value belongs in group2"
--edit
I forgot to mention that this output can change its not always this:
Array(
[0] => Social media campagne
[1] => Marketingcampagne
)
it can also be 3 products for example
It looks like what you want to do relates to set theory. You have a set of things (the return from the function) and you want to see if all the elements in that array are in another array (You want to check if the return array is a strict subset of the array you're checking against).
You can use array_intersect () to do this. This function takes at least 2 arrays as its arguments, and it returns an array of elements that exist in all the arrays passed to it.
If you have an array specifying all the values you want to check against and another array that may or may not be a subset of that array then you can use array_intersect to get a list of all the elements in both arrays. If the number of elements in the output match the number of elements in the array that you want to check then the array must be a strict subset of the array you're checking against.
The following code demonstrates the basic principle:
$set = [1, 2, 3, 4, 5, 6, 7, 8]; // Data you want to test against
$subset = [2, 4, 6, 8]; // Strict subset of $set
$notSubset = [2, 4, 6, 10]; // Not a strict subset of $set because it contains 10
var_dump (count ($subset) === count (array_intersect ($set, $subset))); // true
var_dump (count ($notSubset) === count (array_intersect ($set, $notSubset))); // false
NOTE: array_intersect is only really suitable when the contents of the arrays being compared are all primitive types, as PHP will cast them all to string while comparing them. If you're comparing arrays of arrays or arrays of object then you're better off using array_uintersect () and specifying how the elements are compared yourself with a callback function.
To apply the array_intersect() from #GordonM to your problem (it seems like there are only strings in the arrays).
You first get the number of values from your output, that are in group1
$inGroup1 = array_intersect($ouput, $group1);
$inGroup1Count = count($inGroup1); // you can rewrite these two lines into one,
// if the actual matches are of no interest
If this is the same count as $output, than it's group1. If not, check how many are in group2. I guess you can code that yourself. And then check if inGroup1Count and inGroup2Count are both > 0. Than it's in both groups.
For logic reason you should also check if all are in group 2. Or is that impossible?
With checking both groups you can create an output like
echo $inGroup1Count.' value(s) belongs in group1 and '.$inGroup2Count.' value(s) belongs in group2';

Fast method for Looping through Array to match a common ID in a second array

I'm trying to systematically loop through 2 arrays, and match their values for some quick processing. Let me set up my specific situation:
Array 1
productID,
companyID,
name,
price
Array 2
companyID,
name,
rebate1,
rebate2
I want to loop through Array 1, and when the companyID matches an ID inside of Array 2, I will do some quick math based on the rebate1, rebate2 values for that companyID.
Right now I am looping through Array 1, and then on EACH item in Array 1 I loop through the entire Array 2 to see if the companyID exists. I know this can't be the fastest/cleanest solution...
EDIT
The key values for Array 1 look like:
$array1[0]['productID']
$array1[0]['companyID'] (etc...)
$array1[1]['productID']
$array1[1]['companyID'] (etc...)
The key values for Array 2 look like:
$array2[0]['companyID']
$array2[0]['rebate1'] (etc...)
$array2[1]['companyID']
$array2[1]['rebate1'] (etc...)
Use the companyId as key for Array 2, i.e., make sure that
$Array2[$Array1[$i]['companyID']]['companyID'] == $Array1[$i]['companyID']
This gives you constant time lookup of companies in Array 2 based on companyID and you can do your calculation with
$Array2[$Array1[$i]['companyID']]['rebate1']`
and
$Array2[$Array1[$i]['companyID']]['rebate2']`
Example:
foreach ($Array1 as $value) {
if (isset($Array2[$value['companyID']])) {
//TODO: use $Array2[$value['companyID']] for calculation
} else {
// TODO: handle case companyID not in $Array2
}
}
What approximate sizes do you expect for each of your arrays?
While as you say, your method isn't certainly the fastest (looks like 0(n²)), below 10'000 elements in each array I doubt you can see any significant speed difference.
If you have 150'000 in array1 and 200'000 in array2, that's a whole other story and you'll have to look for an algorithm that is rather 0(log n).
Edit:
As mentioned above, let's just make your array associative if you can:
Instead of:
Array2 = array(
0 => array(
'Company_id' => 'Hello',
'rebate_1' => '50%',
)
);
Make it:
Array2 = array(
'Hello' => array(
'rebate_1' => '50%',
)
);
And then use:
if (isset(array2[$company_id]))
{
// do your stuff
}
If you can't modify Array2's structure where it's coming from, you should transform it on the fly in your search function's scope, so that it looks like above, and then use the transformed array. Transforming Array2 into an associative one shouldn't take too long, for the number of elements you say you have.
The easiest way I can think of is to use the companyID as the key for Array 2:
$companies[$companyID]=array($name,$rebate1,$rebate2)
and then you just reference it directly looping Array 1
$products[$x]=array($productID,$companyID,$name,$price);
...
$newprice1=$products[$x][3]/$companies[$products[$x][1]][1];
$newprice2=$products[$x][3]/$companies[$products[$x][1]][2];
My answer is slightly different from the first one, mind the arrays...
You can create a new array indexed by the company id as follows:
$cid = array_map(function($a) {return $a['companyID'];}, $array2);
$new2 = array_combine($cid, $array2);
With that, you can loop through the first array and access the data:
foreach ($array1 as $key => $value){
$rebate1 = $new2[$value['companyID']]['rebate1'];
$rebate2 = $new2[$value['companyID']]['rebate2'];
}

How to merge multiple arrays that are depending on a function in PHP?

I am seeking for someone's knowledge out here.
Right now, I would need to merge several arrays into a bigger one, but all of those arrays depend on a function.
This function returns a numeric array containing different quantities of numbers between 1 and 7 :
function Possible($i, $j, $grid)
$possible = Possible($i, $j, $grid)
I'm working with a grid, and the function returns a different array for every case of the grid. What I would like to do is to merge those 7 arrays into another one. Some numbers may be present more than once in this big array, but I want it this way.
I tried using for loops, while loops and some other techniques, but nothing worked. In this case, it is not possible to manually define every array, since they change depending of what is contained in the grid and there are too many. It has to be done automatically, and this is where I get stuck.
for ($jj=0; $j<7; $j++){
$possRow = array_merge( ###what do I add here or what do I change in this code to make everything work###
Thank you if someone can help me out!
Etpi
hope this help:
$biggerOneArray = array();
for($k=0;$k<7;$k++) {
$biggerOneArray[] = Possible($i,$j,$grid);
}
Then you can check your bigger array, may contains all arrays of the iterations of the loop (7 arrays merged).
var_dump($biggerOneArray);
The output should be this:
array(
(int) 0 => array(
'key' => 'value',
'key2' => 'value2'
),
(int) 1 => array(
'key3' => 'value3',
'key4' => 'value4'
)
)
etc...
I'm sorry but your description isn't very clear. But just to get you started you might look at this solution.
function Possible($i, $j, $grid) {
// some code ... e.g. $array[] = "some data";
return $array;
}
By creating a small array for each grid and returning it using return $array you get a few little arrays which you can inturn place into a for loop to merge it into one larger array. However i believe the var $jj must have some meaning in the function it self as well.
for($jj=0;$jj<7;$jj++) {
$merged_array[$jj] = Possible($i,$j,$grid);
}
Maybe if you descripe your problem a little more and post an exmple of the array's your working with i can give you a better answer.

Categories