PHP array multidimensional associative - php

$_REQUEST = array(
'articolo' => array(
1 => 1,
3 => 'Sostituzione sostituzioni',
4 => 'Cambio olio'
),
'specifica' => array(
1 => 2,
3 => 'Camoin',
4 => 'Furgone'
),
'quantita' => array(
1 => 3,
3 => 5,
4 => 7
)
);
i need to insert on database like this
$_REQUEST['articolo'][1]
$_REQUEST['specifica'][1]
$_REQUEST['quantita'][1]
on database row and
$_REQUEST['articolo'][3]
$_REQUEST['specifica'][3]
$_REQUEST['quantita'][3]
on another row and ...
$_REQUEST['articolo'][4]
$_REQUEST['specifica'][4]
$_REQUEST['quantita'][4]
i just want to know how to make another array row by row
i need to print
1 -> $_REQUEST['articolo'][1]
2 -> $_REQUEST['specifica'][1]
3 -> $_REQUEST['quantita'][1]
Sostituzione sostituzioni -> $_REQUEST['articolo'][3]
Camoin -> $_REQUEST['specifica'][3]
5 -> $_REQUEST['quantita'][3]
Cambio olio -> $_REQUEST['articolo'][4]
Furgone -> $_REQUEST['specifica'][4]
7 -> $_REQUEST['quantita'][4]
thank

you need something like this:
foreach ($request as $key => $value)
{
$request[$key][1] //row1
$request[$key][3] //row2
$request[$key][4] //row3
}
Edit Based on the comments:
if the array is dynamic(you do not know the keys of the sub-array), you can do this instead:
foreach ($request as $key => $value)
{
foreach ($request[$key] as $key2 => $value2)
{
$request[$key][$key2] //here are your values
}
}
Now you have an idea on how to do it right? use those values inside that foreach to add data to your database

$name = array_keys($_REQUEST);
$index = array_keys($_REQUEST['articolo']);
for($i=0; $i < count($index); $i++):
if($i + 1 % count($index)):
for($j=0; $j < count($name); $j++):
echo $name[$j].': '.$_REQUEST[$name[$j]][$index[$i]].'<br>'."\n";
endfor;
echo '<hr>';
endif;
endfor;
output it's right now
articolo: 1
specifica: 2
quantita: 3
articolo: Sostituzione sotituzioni
specifica: Camoin
quantita: 5
articolo: Cambio olio
specifica: Furgone
quantita: 7
now just need to insert the ordinate data on database

Related

More efficient way of merging two arrays

I am comparing each element of array with every other element of array and if two elements have the same source/target, target/source I merge the inner array with employees e.g.
0=> source - 3 target - 4 officers => 0 - 'Aberdeen Asset Management PLC'
1=> source - 3 target - 4 officers => 0 - 'whatever'
it would be merged to
0=> source - 3 target - 4 officers => 0 - 'Aberdeen Asset Management PLC', 1 - 'whatever'
Here is how the data looks like:
My code is really inefficient with 1000 on more rows to go through the execution takes about 90 seconds which is unacceptable for this sort of thing.
foreach ($edges as $i => &$edge) {
for ($j = $i + 1; $j < count($edges); $j++) {
if ($edge['source'] == $edges[$j]['source'] && $edge['target'] == $edges[$j]['target']) {
foreach ($edges[$j]['officers'] as $officer) {
array_push($edge['officers'], $officer);
}
array_splice($edges, $j, 1);
}
}
}
The solution using array_search, array_keys, array_slice and array_merge functions:
// an exemplary array
$edges = [
0 => ['source' => 3, 'target' => 4, 'officers' => ['Aberdeen Asset Management PLC']],
1 => ['source' => 3, 'target' => 4, 'officers' => ['whatever']],
3 => ['source' => 4, 'target' => 7, 'officers' => ['Jason']],
4 => ['source' => 4, 'target' => 5, 'officers' => ['John']],
5 => ['source' => 4, 'target' => 7, 'officers' => ['Bourne']]
];
foreach ($edges as $k => &$v) {
$next_slice = array_slice($edges, array_search($k, array_keys($edges)) + 1);
foreach ($next_slice as $key => $item) {
if ($item['source'] == $v['source'] && $item['target'] == $v['target']) {
$v['officers'] = array_merge($v['officers'], $item['officers']);
unset($edges[$k + $key + 1]);
}
}
}
print_r($edges);
DEMO link
I think you should do this (updated):
// we will have new array with officers
$new_items = array();
foreach ($edges as $edge) {
// create unique keys for `source-target` and `target-source` pairs
$source_target = $edge['source'] . ':' . $edge['target'];
$target_source = $edge['target'] . ':' . $edge['source'];
// check if unique keys exists in `new_items`
if (!isset($new_items[$source_target]) && !isset($new_items[$target_source])) {
// if unique key doesn't exist - create a new one
$new_items[$source_target] = $edge;
} elseif (isset($new_items[$source_target])) {
// if unique key exists `$source_target` - add an officer to it
$new_items[$source_target]['officers'][] = $edge['officers'][0];
} else {
// if unique key exists `$target_source` - add an officer to it
$new_items[$target_source]['officers'][] = $edge['officers'][0];
}
}
// for returning to numeric indexes use `array_values`
$new_items = array_values($new_items);

Use values that are in all arrays and skip the rest

I have an array with 3 sub arrays like:
$array = array(
width => array(
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5
),
height => array(
0 => 1,
1 => 2,
2 => 7,
3 => 8
),
color => array(
0 => 2,
1 => 7,
2 => 8
)
);
The count is in this case 3 as I have 3 arrays. This can be sometimes more or less, that's why I have a count.
Now I want to find out which number is in all 3 arrays and only use those. in above example the only returned number should be 2 as it's present in all 3 sub arrays.
I was trying something like below, but am really stuck what's the best approach...
$i = count($array); // gives me back the count of 3 which is correct
$n = 0;
foreach($array as $key=>values) {
foreach($values as $value) {
// do not how to proceed :(
}
}
You can call array_intersect with all the sub-arrays as arguments.
$common_values = call_user_func_array('array_intersect', $array);
Maybe you can affect your rows in some var and make what you want to do in your foreach
Like :
<?php
$width = 0;
$height = 0;
$color = 0 ;
$arrayBundleWidth = array();
$arrayBundleHeight = array();
$arrayBundleColor = array();
foreach ($array as $arrayRow){
$arrayBundleWidth = $arrayRow['width'];
$arrayBundleColor = $arrayRow['color'];
$arrayBundleHeight = $arrayRow['height'];
foreach ($arrayBundleWidth as $arrayBundleWidthtRow) {
# code...
#you got each index of your width array here
}
foreach ($arrayBundleHeight as $arrayBundleHeightRow) {
# code...
#you got each index of your height array here
}
foreach ($arrayBundleColor as $arrayBundleColorRow) {
# code...
#you got each index of your color array here
}
}
?>
Try it and tell me ? Is it what you want ?
Not sure if it's what you wanted to do !

How to merge table row with PHP array?

I want to merge the table row if the date have an same id's. I have some array data like this :
Array
(
[0] => Array
(
[id] => 2
[date] => 05/13/2014
[content] => some contents 1
[act] => act1 act2 act3
)
[1] => Array
(
[id] => 2
[date] => 05/28/2014
[content] => some contents 1
[act] => act1 act2 act3
)
[2] => Array
(
[id] => 7
[date] => 06/04/2014
[content] => some contents 2
[act] => act1 act2 act3
)
)
Then I tried to group its data into the same id by :
if($queryx = $this->mymodel->myfunction($par)){
$datax = $queryx;
}
$i = 0;
foreach ($datax as $idx => $val) {
$dates[$val['id']][$i] = $val['date'].",".$val['id'];
$contn[$val['id']][$i] = $val['content'];
$i++;
}
then :
$j = 0; $y = 0;
echo "<table border='1'>\r\n";
foreach ($dates as $idx => $val) {
$tmpexp = explode(',', $val[$j]);
echo "<tr>\r\n";
echo "<td rowspan='".count($val)."'>".$tmpexp[0]."</td>\r\n";
foreach ($val as $idx1 => $val1) {
if($idx1 > 0)
{
echo "<tr>\r\n";
}
echo "<td>".$dates[$tmpexp[1]][$y]."</td>\r\n";
if($idx1 < 1)
{
echo "<td rowspan='".count($val)."'>".$contn[$tmpexp[1]][$y]."</td>\r\n";
echo "<td rowspan='".count($val)."'>act1 act2 act3</td>";
echo "</tr>\r\n";
}
$y++;
}
$j++;
}
echo "</table>";
There is no problem if the data have at least two child, but if the date only have one child (see data with id's 7) there is show an error because Undefined offset. So how I add some handler if there is only one child on the data. There is my desired result:
Please see this image:
I use the 'read ahead' technique for processing nested loops. It does mean that 'foreach' loops cannot be used as the next record must be read as soon as the current one has been processed. Basically, the last action you do in the loop is read the next record as you are setting it up for the next iteration. Note, you never test when to print a record as that is decided by the structure of the groups. The code loops are the same as the structure of the groups in the data
A 'group' is all the records with the same id.
I assume that the 'content' and 'act' are identical for each entry in the group.
Edited to add 'rowspan' attributes to the appropriate 'td' tags. I suspect css may be easier at this point.
The issue is that the group cannot be displayed until it is known how many entries are in it.
So, i 'buffer' all the records belonging to a group in an array. at the end of the group, it is displayed with the appropriate 'rowspan' attributes in the html.
It is tested on PHP 5.3.18. It includes test data.
<?php /* Q24028866 */
$testData = array(array('id' => 2, 'date' => '05/13/2014', 'content' => 'some contents 2', 'act' => 'act1 act2 act3'),
array('id' => 2, 'date' => '05/28/2014', 'content' => 'some contents 2', 'act' => 'act1 act2 act3'),
array('id' => 7, 'date' => '06/04/2014', 'content' => 'some contents 7', 'act' => 'act1 act2 act3'),
array('id' => 8, 'date' => '06/08/2014', 'content' => 'some contents 8', 'act' => 'act1 act2 act3'),
array('id' => 8, 'date' => '06/09/2014', 'content' => 'some contents 8', 'act' => 'act1 act2 act3'));
?>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<table border='1'>
<thead><th>Date</th><th>Content</th><th>Act</th></thead>
<?php
// use 'read ahead' so there is always a 'previous' record to compare against...
$iterContents = new \ArrayIterator($testData);
$curEntry = $iterContents->current();
while ($iterContents->valid()) { // there are entries to process
$curId = $curEntry['id'];
// buffer the group to find out how many entries it has...
$buffer = array();
$buffer[] = $curEntry;
$iterContents->next(); // next entry - may be same or different id...
$curEntry = $iterContents->current();
while ($iterContents->valid() && $curEntry['id'] == $curId) { // process the group...
$buffer[] = $curEntry; // store all records for a group in the buffer
$iterContents->next(); // next entry - may be same or different id...
$curEntry = $iterContents->current();
}
// display the current group in the buffer...
echo '<tr>';
echo '<td>', $buffer[0]['date'], '</td>';
$rowspan = count($buffer) > 1 ? ' rowspan="'. count($buffer) .'"' : '';
echo '<td', $rowspan, '>', $buffer[0]['content'], '</td>',
'<td', $rowspan, '>', $buffer[0]['act'], '</td>';
echo '</tr>';
for($i = 1; $i < count($buffer); $i++) {
echo '<tr><td>', $buffer[$i]['date'], '</td>';
echo '</tr>';
}
} ?>
</table>
</body>
</html>
The following code will give you a clue what you should do,
$newArray = array();
$counter=0;
foreach($datax as $key=>$val){
$newArray[$val['id']][$counter]['date'] = $val['date'];
$newArray[$val['id']][$counter]['content'] = $val['content'];
$newArray[$val['id']][$counter]['act'] = $val['act'];
$counter++;
}
$newArray = array_map('array_values', $newArray);

Deleting Elements In An Array Only When They Are Next To Each Other

I have an array that is composed of information that looks like the following:
['Jay', 'Jay', 'Jay', 'Spiders', 'Dogs', 'Cats', 'John', 'John', 'John', 'Dogs', 'Cows', 'Snakes']
What I'm trying to do is remove duplicate entries but only if they occur right next to each other.
The correct result should look like the following:
['Jay', 'Spiders', 'Dogs', 'Cats', 'John', 'Dogs', 'Cows', 'Snakes']
I'm using PHP but any kind of logic would be able to help me out with this problem.
Here is some code I've tried so far:
$clean_pull = array();
$counter = 0;
$prev_value = NULL;
foreach($pull_list as $value) {
if ($counter == 0) {
$prev_value = $value;
$clean_pull[] = $value;
}
else {
if ($value != $pre_value) {
$pre_value = value;
}
}
echo $value . '<br>';
}
Francis, when I run the following code:
$lastval = end($pull_list);
for ($i=count($pull_list)-2; $i >= 0; $i--){
$thisval = $pull_list[$i];
if ($thisval===$lastval) {
unset($pull_list[$i]);
}
$lastval = $thisval;
}
# optional: reindex the array:
array_splice($pull_list, 0, 0);
var_export($pull_list);
, I get these results:
array ( 0 => 'NJ Lefler', 1 => 'Deadpool', 2 => 'NJ Lefler', 3 => 'Captain Universe: The Hero Who Could Be You', 4 => 'NJ Lefler', 5 => 'The Movement', 6 => 'NJ Lefler', 7 => 'The Dream Merchant', 8 => 'Nolan Lefler', 9 => 'Deadpool', 10 => 'Nolan Lefler', 11 => 'Captain Universe: The Hero Who Could Be You', 12 => 'Nolan Lefler', 13 => 'The Movement', 14 => 'Tom Smith', 15 => 'Deadpool', 16 => 'Tom Smith', 17 => 'Captain Universe: The Hero Who Could Be You', )
Your approach (a $prev_value variable) should work fine and you don't need a counter.
Your use of $counter is why your code doesn't work--the first half of the if statement is always executed because $counter is never incremented; and the second half just compares values. The only thing you need to do is compare the current value with the previous value and include the current value only if it differs (or remove it only if it's the same).
It's much easier to see this algorithm if you use functional reduction. Here is an example using array_reduce:
$a = array('Jay', 'Jay', 'Jay', 'Spiders', 'Dogs', 'Cats', 'John', 'John', 'John', 'Dogs', 'Cows', 'Snakes');
$na = array_reduce($a, function($acc, $item){
if (end($acc)!==$item) {
$acc[] = $item;
}
return $acc;
}, array());
var_export($na);
Note this comparison of var_export($a) (your original array) and var_export($na) (the result produced by the code):
$a = array ( $na = array (
0 => 'Jay', 0 => 'Jay',
1 => 'Jay', 1 => 'Spiders',
2 => 'Jay', 2 => 'Dogs',
3 => 'Spiders', 3 => 'Cats',
4 => 'Dogs', 4 => 'John',
5 => 'Cats', 5 => 'Dogs',
6 => 'John', 6 => 'Cows',
7 => 'John', 7 => 'Snakes',
8 => 'John', )
9 => 'Dogs',
10 => 'Cows',
11 => 'Snakes',
)
The array_reduce() method does exactly the same thing as the following code:
$na = array();
foreach ($a as $item) {
if (end($na)!==$item) {
$na[] = $item;
}
}
Instead of returning a copy of an array, you can also modify the array in-place using the same algorithm but starting from the end of the array:
$lastval = end($a);
for ($i=count($a)-2; $i >= 0; $i--){
$thisval = $a[$i];
if ($thisval===$lastval) {
unset($a[$i]);
}
$lastval = $thisval;
}
# optional: reindex the array:
array_splice($a, 0, 0);
var_export($a);
Keep track of the last element in the array, and skip adding the next element to your new array if you just added it.
Or, you can just check the last element in the array, and see if it's not the current element in your array:
$array = ['Jay', 'Jay', 'Jay', 'Spiders', 'Dogs', 'Cats', 'John', 'John', 'John', 'Dogs', 'Cows', 'Snakes'];
$new = array( array_shift( $array));
foreach( $array as $el) {
if( !($new[count($new) - 1] === $el)) {
$new[] = $el;
}
}
Assuming the array isn't so large that having a second one will cause a problem, the approach you described should work. Does it look like this?
$last = null;
$result = [];
foreach($arr as $item)
if($item !== $last)
$result[] = $last = $item;
Re: edit:
$pre_value and $prev_value aren't the same thing
$counter doesn't change
It looks like you tried to combine a counter approach and a "last" approach somehow.
Define a global variable glob.
pass the array:
if (array[i] == glob) then
remove array[i]
else
glob = array[i];
keep array[i];

How to use foreach to verify value in a 3-dimensional array without having duplicated output in php?

Hi my question is a little tricky, I got a 3-dimensional array and try to verify the 3rd level value and echo both 1st and 3rd level values.
The following is the code example, and my failed approaches.
$myArray=array(
"mySub0" => arrary(
0 => array("mySubSub0" => "1","mySubSub1" => "a"),
1 => array("mySubSub0" => "2","mySubSub1" => "b"),
2 => array("mySubSub0" => "3","mySubSub1" => "b"),
),
"mySub1" => arrary(
0 => array("mySubSub0" => "4","mySubSub1" => "a"),
1 => array("mySubSub0" => "5","mySubSub1" => "a"),
2 => array("mySubSub0" => "6","mySubSub1" => "a"),
),
"mySub2" => arrary(
0 => array("mySubSub0" => "7","mySubSub1" => "a"),
1 => array("mySubSub0" => "8","mySubSub1" => "b"),
2 => array("mySubSub0" => "9","mySubSub1" => "a"),
),
),
I want to check if the value of "mySubSub1" is b. if yes, echo the value of "mySubSub0" and the related key in first-level of the array. It should be like this:
mySub0
2
3
mySub2
8
My failed approach is
foreach ($myArray as $a => $b)
{
foreach ($b as $c)
if($c[mySubSub1]=="b")
{
echo $a
echo $c[mySubSub0];
}
else {
}
}
The result will have one duplicate mySub0
mySub0
2
mySub0
3
mySub2
8
if I move the "echo $a" out of the "if"
foreach ($myArray as $a => $b)
{
echo $a
foreach ($b as $c)
if($c[mySubSub1]=="b")
{
echo $c[mySubSub0];
}
else {
}
}
the result would be
mySub0
2
3
mySub1
mySub2
8
one unwanted "mySub1" because there is no place to verify if there is a value b.
It has bothered my a lot today. I tried to Google but haven't found the right answer.
Really hope someone can help me. Thank you in advance
Here's something that should work:
function find_value($arr, $key, $value, $sibling)
{
foreach ($arr as $k => $v)
{
$results = _find_value($v, $key, $value, $sibling);
if (count($results) > 0) {
echo $k;
foreach ($results as $result) {
echo $result;
}
}
}
}
function _find_value($arr, $key, $value, $sibling)
{
$out = array();
foreach ($arr as $k => $v)
{
if ($v[$key] == $value)
$out[] = $v[$sibling];
}
return $out;
}
find_value($myArray, "mySubSub1", "b", "mySubSub0");
Basically, the main function loops over items in the outer array, calling the inner function to get a list of the "sibling" keys where the main key matches the value you're looking for. If a non-zero number of results are obtained in the inner function, echo and loop.
Hopefully this does the trick for you.

Categories