I have 5 different arrays which I need to use to generate a table showing the info. This table cannot have duplicates. This is in a way a fairly easy task, but what I am looking for is the most elegant solution - one that doesn't require lots of for loops, array merging etc etc.
The table needs to output information for photo printing. And should look a bit like this:
Not like this:
The arrays look like this:
//img arr:
$img_arr = array(array('002_chrysanthemum', '6x4'), array('002_chrysanthemum', '9x6'));
//size arr:
$size_arr = array('6x4', '9x6');
//finish arr:
$finish_arr = array('glossy', 'glossy');
//qty arr:
$qty_arr = array(2, 3);
//media arr:
$media_arr = array('std', 'std');
Thanks.
EDIT - Typo with finish / qty arr pointed out, changed, thanks.
Group your images into an array indexed first by image name and second by its size.
Loop through each size to render the column headers, then loop through each grouped image to render the rows.
$img_arr = array(array('002_chrysanthemum', '6x4'), array('002_chrysanthemum', '9x6'));
$size_arr = array('6x4', '9x6');
$finish_arr = array('glossy', 'glossy');
$qty_arr = array(2, 3);
$media_arr = array('std', 'std');
$images = array();
foreach($img_arr as $key => $img) {
$images[$img[0]][$img[1]] = array(
'finish' => $finish_arr[$key],
'qty' => $qty_arr[$key],
'media' => $media_arr[$key],
);
}
print "<table>";
print "<tr><th></th>";
foreach($size_arr as $size) {
print "<th>$size</th>";
}
print "</tr>";
foreach($images as $name => $image) {
print "<tr><td>$name</td>";
foreach($size_arr as $size) {
print "<td>" . $image[$size]['qty']
. '#' . $image[$size]['finish']
. ' ' . $image[$size]['media'] . "</td>";
}
print "</tr>";
}
print "</table>";
$img_arr = array('002_chrysanthemum', '002_chrysanthemum');
$size_arr = array('6x4', '9x6');
$finish_arr = array('glossy', 'glossy');
$qty_arr = array(2, 3);
$media_arr = array('std', 'std');
Could be combined into one sensible array like:
foreach($img_arr as $k=>$img) {
foreach($size_arr as $size) {
$prints[$img][$size]['finish'] = $finish_arr[$k];
$prints[$img][$size]['qty'] = $qty_arr[$k];
$prints[$img][$size]['media'] = $media_arr[$k];
}
}
The result, which is based on the idea that image array is the x-axis and sizes are the y-axis and all other arrays are properties based on position to the y-axis. So then:
print_r($prints);
returns
Array (
[002_chrysanthemum] => Array
(
[6x4] => Array
(
[finish] => glossy
[qty] => 3
[media] => std
)
[9x6] => Array
(
[finish] => glossy
[qty] => 3
[media] => std
)
)
)
Which is the very elegant and simple data collection that you want to transform into a table, which it can be now that it is normalized.
Related
To calculate the sum of values based on the input and match it with names in an array
$input = '500';
$array1 = array("200" => 'jhon',"300" => 'puppy',"50" => 'liza',
"150" => 'rehana',"400" => 'samra',"100" => 'bolda',);
need answer like this output
jhon,puppy and bolda,rehana
This code creates an array $data that contains names and their respective values. It then uses a foreach loop to iterate through the array and subtract the value of each name from the input until the input becomes zero. The names of all the values that were subtracted from the input are stored in an array $names. Finally, if the array $names is not empty, the names are echoed using implode separated by "and". If the array is empty, it means no match was found and a message "No match found" is echoed.
So I'm going to go out on a guess here. (this sounds like cheating on homework lmao).
You need to output pairs of names where the two names add upto 500 (the input).
This probably wont be the most optimal solution, but it should be a solution that works?
$input = 500;
// using shorthand array formatting
$array1 = [
200 => 'jhon',
300 => 'puppy',
50 => 'liza',
150 => 'rehana',
400 => 'samra',
100 => 'bolda'
];
// create an array that holds names we have already processed.
$namesProcessed = [];
// loop over the names trying to find a compatible partner
foreach ($array1 as $points => $name) {
foreach ($array1 as $pointsPotentialPartner => $namePotentialPartner) {
// Don't partner with yourself...
if ($name == $namePotentialPartner) {
continue;
}
// Don't partner with someone that has already been processed.
if (in_array($namePotentialPartner, $namesProcessed)) {
continue;
}
// test if the two partners add up to the input
if ($input == ($points + $pointsPotentialPartner)) {
// if this is the first partner set, don't put in 'and'
if (count($namesProcessed) == 0) {
echo $name . ', ' . $namePotentialPartner;
} else {
echo ' and ' . $name . ', ' . $namePotentialPartner;
}
$namesProcessed[] = $name;
$namesProcessed[] = $namePotentialPartner;
}
}
}
Hope this helps.
I am counting the elements of an array and storing the result in an array using array_count_values.
Let's consider this is the output for this instance, which is created from an array, which was in-turn created with the help of explode.
magazine = Array(
[avatar] => 1
[essence] => 6
[pie] => 1
[multiplex] => 1
[bill] => 2
[nice] => 2
[pie ] => 1
)
ransom = Array(
[multiplex] => 1
[pie] => 2
[avatar] => 3
[bill] => 1
[nice] => 3
[essence] => 1
)
Now, I want to check if the elements in Array ransom are available in array Magazine.
The loop should exit if the element in ransom is not available in magazine. (or) If the element exists, value of that element in ransom cannot be greater than the same element value in magazine.
How can I achieve this? How to use nested foreach in this case? as I cannot use a simple for loop here because of the keys.
$ransom_temp = "avatar essence pie multiplex bill nice essence nice bill essence essence essence essence pie"
$magazine_temp = "multiplex pie pie avatar bill nice nice nice avatar essence avatar"
$magazine = explode(" ",$magazine_temp);
$ransom = explode(" ",$ransom_temp);
$countRan = array_count_values($ransom);
$countMag = array_count_values($magazine);
print_r($countMag);
print "<br>";
print_r($countRan);
if($n > $m){
print "No";
return;
}
foreach($countRan as $key1=>$value1){
foreach($countMag as $key2=>$value2)
if($key1 != $key2) || $value1 > $value2){
print "No";
return;
}
}
print "Yes";
You only need one loop:
$ransom_temp = "avatar essence pie multiplex bill nice essence nice bill essence essence essence essence pie"
$magazine_temp = "multiplex pie pie avatar bill nice nice nice avatar essence avatar"
$magazine = explode(" ",$magazine_temp);
$ransom = explode(" ",$ransom_temp);
$countRan = array_count_values($ransom);
$countMag = array_count_values($magazine);
print_r($countMag);
print "<br>";
print_r($countRan);
if(count($countRan) > count($countMag)) {
print "No";
return;
}
foreach ($countRan as $key => $value){
// exit if key not exists in $countMag array
// or exit if value in $countRan[$key] greater than $countMag[$key]
if (!array_key_exists($key, $countMag) || $value > $countMag[$key]) {
print "No";
return;
}
}
print "Yes";
I'm getting an error whilst trying to iterate some data and I can't figure out what I'm doing wrong. This is the format of the data I have returned from an API request:
Array
(
[search-results] => Array
(
[entry] => Array
(
[0] => Array
(
[author] => Array
(
[0] => Array
(
[authname] => Griffin J.
[surname] => Griffin
[initials] => J.M.
)
[1] => Array
(
[authname] => Williams D.
[surname] => Williams
[initials] => D.H.
)
)
)
[1] => Array
( ...etc...
)
)
)
)
For reference the above data printout is from $eachJson in the code below.
I can only do an API request to get 100 results at a time, so I set up a for loop to perform the search 100 times, then next 100 etc. As there are multiple authors per record, I set up a foreach loop to iterate the authors and this is where I'm getting the error messages:
Notice: Undefined index: author in C:\xampp\htdocs\academic_intelligence\public\ScopusTest.php on line 42
Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\academic_intelligence\public\ScopusTest.php on line 42
Here's the code:
$apiKey = "&apiKey=c2cb86c3a511ed34dd6f03f481c637c1";
$search1 = urlencode("badgers");
$search2 = urlencode(" OR weasels");
$start = 0;
$scopusData = [];
// create an array to represent citation values to ignore, i.e. not interested
// in any publications with less than 4 citations
$ignore = array(0, 1, 2, 3);
// set processing time for browser before timeout
ini_set('max_execution_time', 3600);
// override default PHP memory limit
ini_set('memory_limit', '-1');
// REST HTTP GET Request searching for people associated with keywords (term)
$searchLink = "http://api.elsevier.com/content/search/scopus?query=KEY(" . $search1 . $search2 . ")" . $apiKey . "&sort=citedby-count&count=100&start=" . $start . "&view=complete";
// save results to a variable
$searchResponse = file_get_contents($searchLink);
// convert JSON to PHP variable
$searchJson = json_decode($searchResponse, true);
// get total number of results for query to know when to stop iterating data
$total = $searchJson['search-results']['opensearch:totalResults'];
// iterate data loading next 200 results (max) each time and adding new results to array
for ($i = $start; $i <= $total; $i+=100) {
// REST HTTP GET Request searching for people associated with keywords (term)
$eachLink = "http://api.elsevier.com/content/search/scopus?query=KEY(" . $search1 . $search2 . ")" . $apiKey . "&sort=citedby-count&count=100&start=" . $i . "&view=complete";
// save results to a variable
$eachResponse = file_get_contents($eachLink);
$eachJson = json_decode($eachResponse, true);
foreach ($eachJson['search-results']['entry'] as $record) {
// array to store authors
$authors = [];
foreach ($record['author'] as $thisAuthor) { // **LINE 42**
// push initials and surname to array
array_push($authors, ($thisAuthor['initials'] . $thisAuthor['surname']));
};
// scopus ID
$scopusID = $record['dc:identifier'];
// paper title
$title = $record['dc:title'];
// date
$date = substr($record['prism:coverDate'], 0, 4);
// citations, if less than 4 then break out of iteration
if (!in_array(($cites = $record['citedby-count']), $ignore)) {
$cites = $record['citedby-count'];
} else {
break 2;
}
$thisData = [
"authors" => $authors,
"ID" => $scopusID,
"title" => $title,
"date" => $date,
"cites" => $cites
];
array_push($scopusData, $thisData);
}
};
// need to replace single quotes to avoid char escape
for ($i = 0; $i < count($scopusData); $i++) {
foreach ($scopusData[$i]['authors'] as &$edit) {
$edit = str_replace("'", "", $edit);
};
$scopusData[$i]['title'] = str_replace("'", "", $scopusData[$i]['title']);
};
I've highlighted line 42 which is causing the error. This must be something straightforward but it's been a long day and I can't figure out the problem! I still get the correct data at the end, the final array scopusData includes all the authors taken from that faulty foreach loop so it seems strange that I'm getting the error.
Are you sure that each record contains an author element?
Maybe you should add an ifset($record['author']) ahead of the foreach() loop.
(re-posted comment as an answer as OP's request)
I have 2 arrays - the first one is output first in full. The 2nd one may have some values that were already used/output with the first array. I want to "clean up" the 2nd array so that I can output its data without worrying about showing duplicates. Just to be sure I have the terminology right & don't have some sort of "array within an array", this is how I access each one:
1st Array
$firstResponse = $sth->fetchAll();
foreach ($firstResponse as $firstResponseItem) {
echo $firstResponseItem['samecolumnname']; // Don't care if it's in 2nd array
}
2nd Array
while( $secondResponseRow = $dbRequest->fetch_assoc() ){
$secondResponseArray = array($secondResponseRow);
foreach ($secondResponseArray as $secondResponseItem){
echo $secondResponseItem['samecolumnname']; //This can't match anything above
}
}
Thanks!
For example:
$response_names = array();
$firstResponse = $sth->fetchAll();
foreach ($firstResponse as $firstResponseItem)
$response_names[] = $firstResponseItem['samecolumnname'];
while( $secondResponseRow = $dbRequest->fetch_assoc() ){
$secondResponseArray = array($secondResponseRow);
foreach ($secondResponseArray as $secondResponseItem) {
if (!in_array($secondResponseItem['samecolumnname'], $response_names))
$response_names[] = $secondResponseItem['samecolumnname'];
}
}
array_walk($response_names, function($value) { echo $value . '<br />' });
If I understand what you're looking to do and the arrays are in the same scope, this should work.
$secondResponseArray = array($secondResponseRow);
$secondResponseArray = array_diff($secondResponseArray, $firstResponse);
//secondResponseArray now contains only unique items
foreach ($secondResponseArray as $secondResponseItem){
echo $secondResponseItem['samecolumnname'];
}
If you know that the keys of duplicate values will be the same you could use array_diff_assoc to get the items of the first array that aren't in the other supplied arrays.
This code
<?php
$a = array('abc', 'def', 'ghi', 'adg');
$b = array('abc', 'hfs', 'toast', 'adgi');
$r = array_diff_assoc($b, $a);
print_r($a);
print_r($r);
produces the following output
[kernel#~]php so_1.php
Array
(
[0] => abc
[1] => def
[2] => ghi
[3] => adg
)
Array
(
[1] => hfs
[2] => toast
[3] => adgi
)
[kernel#~]
I am using the following code to populate an array:
$number = count ($quantitys);
$count = "0";
while ($count < $number) {
$ref[$count] = postcodeUnknown ($prefix, $postcodes[$count]);
$count = $count +1;
}
postcodeUnknown returns the first row from a mysql query, using a table prefix and an element from an array named postcodes. $postcodes contains strings that should return a different row each time though the loop.
Which I'd expect to create an array similar to:
Array ([0] =>
Array ([0] => some data [1] => more data)
[1] =>
Array ([0] => second row [1] => even more...)
)
But it's not. Instead it's creating a strange array containing the first results over and over until the condition is met, eg:
simplified result of print_r($ref);
Array (
[0] => Array ([0] => some data [1] => more data)
)
Array(
[0] => Array (
[0] => the first arrays content...
[1] => ...repeated over again until the loop ends
)
)
And I'm at a loss to understand why. Anyone know better than me.
Try
$number = count ($quantitys);
$count = "0";
while ($count < $number) {
$ref1[$count] = postcodeUnknown ($prefix, $postcodes[$count]);
$ref2[] = postcodeUnknown ($prefix, $postcodes[$count]);
$ref3[$count][] = postcodeUnknown ($prefix, $postcodes[$count]);
$count = $count +1;
}
echo "<pre>";
print_r($ref1);
print_r($ref2);
print_r($ref3);
echo "</pre>";
Try that to see if any of those get an output you are looking for.
Uh, add a print to postcodeUnknown and check if its actually passing different postcodes or the same thing all the time?
ie
function postcodeUnkown($a,$b){
echo var_dump($a).var_dump($b);
//the rest
}
Also, why two different variables? ($quantitys and $postcodes).
Also, you might want to replace the while loop with for:
for($i=0;$i<$number;$i++){
$ref[$i] = postcodeUnknown ($prefix, $postcodes[$i]);
}
your variable count should not be a string, try this
$number = count ($quantitys);
$count = 0;
while ($count < $number) {
$ref[$count] = postcodeUnknown ($prefix, $postcodes[$count]);
$count = $count +1;
}