I have an array with float indexes that I'm getting from a plugin. I want to parse this array and take the ones that are float and put them in as a new array. Meaning what I have is
[1] => gsurvey128f54af2
[2] => gsurvey282bd4253
[5.1] => gsurvey5649a964f
[5.2] => gsurvey5fddb5e9f
[5.3] => gsurvey533c5b311
[5.4] => gsurvey5c8933efb
[5.5] => gsurvey5da48f59b
What I want is:
[1] => gsurvey128f54af2
[2] => gsurvey282bd4253
[5] => array (
[0] => gsurvey5649a964f
[1] => gsurvey5fddb5e9f
[2] => gsurvey533c5b311
[3] => gsurvey5c8933efb
[4] => gsurvey5da48f59b
)
I'm not clear on what's the best way to approach this.
I made the comment above that this problem is very prone to error because it is possible to have input that would set a single value to be both a string and an array at the same time. That will obviously fail. Assuming that the input is clean...
$new_array = array();
foreach($old_array as $key=>$val)
{
$a = explode('.', $key);
if(sizeof($a)==2)
{
if(!isset($new_array[$a[0]])) $new_array[$a[0]] = array();
$new_array[$a[0]][] = $val;
}
else $new_array[$key]=$val;
}
Example with array_walk:
$array = array (
'1' => 'gsurvey128f54af2',
'2' => 'gsurvey282bd4253',
'5.1' => 'gsurvey5649a964f',
'5.2' => 'gsurvey5fddb5e9f',
'5.3' => 'gsurvey533c5b311',
'5.4' => 'gsurvey5c8933efb',
'5.5' => 'gsurvey5da48f59b'
);
$output = array();
array_walk( $array, function( $item, $key ) use ( &$output ) {
$keys = explode( '.', $key );
isset( $keys[1] ) ? $output[ $keys[0] ][ $keys[1] ] = $item : $output[ $keys[0] ] = $item;
});
print_r( $output );
/*
Array
(
[1] => gsurvey128f54af2
[2] => gsurvey282bd4253
[5] => Array
(
[1] => gsurvey5649a964f
[2] => gsurvey5fddb5e9f
[3] => gsurvey533c5b311
[4] => gsurvey5c8933efb
[5] => gsurvey5da48f59b
)
)
*/
For this specific case, this should work:
foreach($array as $k => $v) {
if(count($i = explode('.', $k)) > 1) {
$result[$i[0]][] = $v;
} else {
$result[$k] = $v;
}
}
Related
Goal: Generate an array that includes only those 'columns' with data, even though a 'header' may exist.
Example Data:
Array (
[HeaderRow] => Array (
[0] => Employee [1] => LaborHours [2] => 0.1 [3] => 0.25 [4] => 0.5 [5] => 0.8
)
[r0] => Array (
[0] => Joe [1] => 5 [2] => [3] => [4] => 50 [5] =>
)
[r1] => Array (
[0] => Fred [1] => 5 [2] => 10 [3] => [4] => [5] =>
)
)
Desired Output:
Array (
[HeaderRow] => Array (
[0] => Employee [1] => LaborHours [2] => 0.1 [4] => 0.5
)
[r0] => Array (
[0] => Joe [1] => 5 [2] => [4] => 50
)
[r1] => Array (
[0] => Fred [1] => 5 [2] => 10 [4] =>
)
)
So, in this very dumbed down example, the HeaderRow will always have data, but if both c0 and c1 are empty (as is the case for [3] and [5]) then I want to remove. I tried iterating through with for loops like I would in other languages, but that apparently doesn't work with associative arrays. I then tried doing a transpose followed by two foreach loops, but that failed me as well. Here's a sample of my for loop attempt:
Attempt with For Loop
for ($j = 0; $j <= count(reset($array))-1; $j++) {
$empty = true;
for ($i = 1; $i <= count($array)-1; $i++) {
if(!empty($array[$i][$j])) {
$empty = false;
break;
}
}
if ($empty === true)
{
for ($i = 0; $i <= count($array); $i++) {
unset($array[$i][$j]);
}
}
}
return $array;
Attempt with transpose:
$array = transpose($array);
foreach ($array as $row)
{
$empty = true;
foreach ($row as $value)
{
if (!empty($value))
{
$empty = false;
}
}
if ($empty) {
unset($array[$row]);
}
}
$array = transpose($array);
return $array;
function transpose($arr) {
$out = array();
foreach ($arr as $key => $subarr) {
foreach ($subarr as $subkey => $subvalue) {
$out[$subkey][$key] = $subvalue;
}
}
return $out;
}
I know the transpose one isn't terribly fleshed out, but I wanted to demonstrate the attempt.
Thanks for any insight.
We can make this more simpler. Just get all column values using array_column.
Use array_filter with a custom callback to remove all empty string values.
If after filtering, size of array is 0, then that key needs to be unset from all
subarrays.
Note: The arrow syntax in the callback is introduced since PHP 7.4.
Snippet:
<?php
$data = array (
'HeaderRow' => Array (
'0' => 'Employee','1' => 'LaborHours', '2' => 0.1, '3' => 0.25, '4' => 0.5, '5' => 0.8
),
'r0' => Array (
'0' => 'Joe', '1' => 5, '2' => '','3' => '', '4' => 50, '5' => ''
),
'r1' => Array (
'0' => 'Fred', '1' => 5,'2' => 10, '3' => '', '4' => '', '5' => ''
)
);
$cleanup_keys = [];
foreach(array_keys($data['HeaderRow']) as $column_key){
$column_values = array_column($data, $column_key);
array_shift($column_values); // removing header row value
$column_values = array_filter($column_values,fn($val) => strlen($val) != 0);
if(count($column_values) == 0) $cleanup_keys[] = $column_key;
}
foreach($data as &$row){
foreach($cleanup_keys as $ck){
unset($row[ $ck ]);
}
}
print_r($data);
It figures, I work on this for a day and have a moment of clarity right after posting. The answer was that I wasn't leveraging the Keys.:
function array_cleanup($array)
{
$array = transpose($array);
foreach ($array as $key => $value)
{
$empty = true;
foreach ($value as $subkey => $subvalue)
{
if ($subkey != "HeaderRow") {
if (!empty($subvalue))
{
$empty = false;
}
}
}
if ($empty) {
unset($array[$key]);
}
}
$array = transpose($array);
return $array;
}
I have the following PHP array
[1] => Array
(
[0] => 9780881220766
[1] => 0881220760
)
[2] => Array
(
[0] => 9780141374284
[1] => 0141374284
)
[3] => Array
(
[0] => 057305133X
[1] => 9780573051333
))
I would like the output to be as follows:
[0] => 9780881220766
[1] => 0881220760
[2] => 9780141374284
[3] => 0141374284
[4] => 057305133X
[5] => 9780573051333
I tried using array_values but I'm not getting any output.
I also tried to extract the values using a foreach loop:
foreach ($rawIsbns as $isbnKey => $isbnValue){
$formattedIsbns[] = $isbnValue;
}
However, I'm not managing.
$a = array();
foreach ($array as $tmp) {
if (is_array($tmp)) $a = array_merge($a, $tmp);
}
Created this function that allows you to merge 1 or more arrays together into the format you asked for:
function sortarr(...$arr){
$tmparr = [];
foreach($arr as $aa) foreach($aa as $a) $tmparr = array_merge($tmparr, $a);
return $tmparr;
}
Example Usage:
<?php
# First array provided
$array = array(
[
"9780881220766",
"0881220760"
],
[
"9780141374284",
"0141374284"
],
[
"057305133X",
"9780573051333"
]
);
# Second array just to show how you can input more than 1 array into the function
$array2 = array(
[
"6234808972234",
"67834757"
],
[
"0287568924344234",
"234690543"
],
[
"34565786978099x",
"3569876546"
]
);
function sortarr(...$arr){
# Declare our temp array
$tmparr = [];
# Iterates through each of the arrays inside the array(s) provided
foreach($arr as $aa) foreach($aa as $a) $tmparr = array_merge($tmparr, $a);
# Return the results
return $tmparr;
}
print_r( sortarr($array, $array2) );
Results:
Array
(
[0] => 9780881220766
[1] => 0881220760
[2] => 9780141374284
[3] => 0141374284
[4] => 057305133X
[5] => 9780573051333
[6] => 6234808972234
[7] => 67834757
[8] => 0287568924344234
[9] => 234690543
[10] => 34565786978099X
[11] => 3569876546
)
Live Demo: http://sandbox.onlinephpfunctions.com/code/838a108498f446ae4a5f8e42fa441ec11941c567
I managed to solve the problem by initializing an array and adding values of subsequent nested arrays using array_push
function isbns($rawIsbns) {
$prevArrayValues = null;
foreach ($rawIsbns as $value) {
if (!isset($prevArrayValues)) {
$prevArrayValues = []; //initiallise first value unless initialized
}
if (empty($value)) {
$return = []; //disregard empty values
} else {
$return = $value; // add arrays to existing array
}
$prevArrayValues = array_merge($prevArrayValues, $return);
}
return $prevArrayValues;
}
I want to create a list where if its already in the array to add to the value +1.
Current Output
[1] => Array
(
[source] => 397
[value] => 1
)
[2] => Array
(
[source] => 397
[value] => 1
)
[3] => Array
(
[source] => 1314
[value] => 1
)
What I want to Achieve
[1] => Array
(
[source] => 397
[value] => 2
)
[2] => Array
(
[source] => 1314
[value] => 1
)
My current dulled down PHP
foreach ($submissions as $timefix) {
//Start countng
$data = array(
'source' => $timefix['parent']['id'],
'value' => '1'
);
$dataJson[] = $data;
}
print_r($dataJson);
Simply use an associated array:
$dataJson = array();
foreach ($submissions as $timefix) {
$id = $timefix['parent']['id'];
if (!isset($dataJson[$id])) {
$dataJson[$id] = array('source' => $id, 'value' => 1);
} else {
$dataJson[$id]['value']++;
}
}
$dataJson = array_values($dataJson); // reset the keys - you don't nessesarily need this
This is not exactly your desired output, as the array keys are not preserved, but if it suits you, you could use the item ID as the array key. This would simplify your code to the point of not needing to loop through the already available results:
foreach ($submissions as $timefix) {
$id = $timefix['parent']['id'];
if (array_key_exists($id, $dataJson)) {
$dataJson[$id]["value"]++;
} else {
$dataJson[$id] = [
"source" => $id,
"value" => 1
];
}
}
print_r($dataJson);
You should simplify this for yourself. Something like:
<?
$res = Array();
foreach ($original as $item) {
if (!isset($res[$item['source']])) $res[$item['source']] = $item['value'];
else $res[$item['source']] += $item['value'];
}
?>
After this, you will have array $res which will be something like:
Array(
[397] => 2,
[1314] => 1
)
Then, if you really need the format specified, you can use something like:
<?
$final = Array();
foreach ($res as $source=>$value) $final[] = Array(
'source' => $source,
'value' => $value
);
?>
This code will do the counting and produce a $new array as described in your example.
$data = array(
array('source' => 397, 'value' => 1),
array('source' => 397, 'value' => 1),
array('source' => 1314, 'value' => 1),
);
$new = array();
foreach ($data as $item)
{
$source = $item['source'];
if (isset($new[$source]))
$new[$source]['value'] += $item['value'];
else
$new[$source] = $item;
}
$new = array_values($new);
PHP has a function called array_count_values for that. May be you can use it
Example:
<?php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
?>
Output:
Array
(
[1] => 2
[hello] => 2
[world] => 1
)
I have an array containing strings of this format:
[0] => "title|url|score|user|date"
[1] => "title|url|score|user|date"
[2] => "title|url|score|user|date"
[3] => "title|url|score|user|date"
...
The score field is an int that is not always unique (for example, more than one entry can have a score of 0). I'm looking to sort the strings in this array based on their score value. Originally, I tried iterating through the array and making a new one with keys corresponding to the vote score. I soon realized that you can't have duplicate keys in an array.
Is there a good clean way of doing this?
$array = array(
0 => "title|url|12|user|date",
1 => "title|url|0|user|date",
2 => "title|url|13|user|date",
3 => "title|url|0|user|date"
);
function sortOnScore( $a, $b )
{
// discard first two values
list( ,,$scoreA ) = explode( '|', $a );
list( ,,$scoreB ) = explode( '|', $b );
return $scoreA == $scoreB ? 0 : ( $scoreA > $scoreB ? 1 : -1 );
}
usort( $array, 'sortOnScore' );
var_dump( $array );
Look into PHP's usort function
function score_sort($rec1, $rec2)
{
return $rec1['score'] - $rec2['score'];
}
usort($score_array);
Replace ['score'] with however you are extracting the scores from the strings
First you need to turn the strings into arrays with explode so you can do the comparisons:
// If using PHP >= 5.3, this can also be made into an anonymous function
function converter($string) {
$result = array_combine(
array('title', 'url', 'score', 'user', 'date'),
explode('|', $string)
);
// When these are later compared, it should be as numbers
$result['score'] = (int)$result['score'];
return $result;
}
$input = array(
'Foo|http://foo|0|user1|today',
// etc.
);
$converted = array_map('converter', $input);
This will make $converted look like:
array (
0 => array (
'title' => 'Foo',
'url' => 'http://foo',
'score' => '0',
'user' => 'user1',
'date' => 'today',
),
)
Then you can sort the array using the code from my answer here by easily specifying any sort criteria you want:
usort($converted, make_converter('score', 'date', 'title'));
Personally I'd be tempted to iterate through the array, split it by the |'s and put it into a new multi-dimensional array, for example something like this:
[0] => array([title]=>'title',[url]=>'url',[score]=>'score',[user]=>'user',[date]=>'date')
[1] => array([title]=>'title',[url]=>'url',[score]=>'score',[user]=>'user',[date]=>'date')
Then it becomes easy to sort, just use a function like this:
function sortmulti ($array, $index, $order, $natsort=FALSE, $case_sensitive=FALSE) {
if(is_array($array) && count($array)>0) {
foreach(array_keys($array) as $key) {
$temp[$key]=$array[$key][$index];
}
if(!$natsort) {
if ($order=='asc') {
asort($temp);
} else {
arsort($temp);
}
}
else
{
if ($case_sensitive===true) {
natsort($temp);
} else {
natcasesort($temp);
}
if($order!='asc') {
$temp=array_reverse($temp,TRUE);
}
}
foreach(array_keys($temp) as $key) {
if (is_numeric($key)) {
$sorted[]=$array[$key];
} else {
$sorted[$key]=$array[$key];
}
}
return $sorted;
}
return $sorted;
}
i.e. do this:
$sortedarray = sortmulti($array,'score','asc');
It would be very easy using the asort function:
$pattern = '#^([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)$#';
$sorted = array();
foreach($data as $s) $sorted[] = preg_replace($pattern, '$3|$1|$2|$4|$5', $s);
asort($sorted);
these 4 lines of code, when given $data:
Array
(
[0] => title_0|url_0|6|user_0|date_0
[1] => title_1|url_1|6|user_1|date_1
[2] => title_2|url_2|2|user_2|date_2
[3] => title_3|url_3|3|user_3|date_3
[4] => title_4|url_4|2|user_4|date_4
[5] => title_5|url_5|7|user_5|date_5
[6] => title_6|url_6|3|user_6|date_6
[7] => title_7|url_7|8|user_7|date_7
[8] => title_8|url_8|3|user_8|date_8
[9] => title_9|url_9|9|user_9|date_9
)
will generate $sorted:
Array
(
[2] => 2|title_2|url_2|user_2|date_2
[4] => 2|title_4|url_4|user_4|date_4
[3] => 3|title_3|url_3|user_3|date_3
[6] => 3|title_6|url_6|user_6|date_6
[8] => 3|title_8|url_8|user_8|date_8
[0] => 6|title_0|url_0|user_0|date_0
[1] => 6|title_1|url_1|user_1|date_1
[5] => 7|title_5|url_5|user_5|date_5
[7] => 8|title_7|url_7|user_7|date_7
[9] => 9|title_9|url_9|user_9|date_9
)
and with just 2 more lines you can have the items in each element of the array back in the original order/format:
$data = array();
foreach($sorted as $s) $data[] = preg_replace($pattern, '$2|$3|$1|$4|$5', $s);
setting $data to:
Array
(
[0] => title_2|url_2|2|user_2|date_2
[1] => title_4|url_4|2|user_4|date_4
[2] => title_3|url_3|3|user_3|date_3
[3] => title_6|url_6|3|user_6|date_6
[4] => title_8|url_8|3|user_8|date_8
[5] => title_0|url_0|6|user_0|date_0
[6] => title_1|url_1|6|user_1|date_1
[7] => title_5|url_5|7|user_5|date_5
[8] => title_7|url_7|8|user_7|date_7
[9] => title_9|url_9|9|user_9|date_9
)
Create a new array of arrays:
[0] => array("score", old_array[0])
Then sort.
foreach ($this->CsInventory as $value)
{
print_r($value) // print 1
$vname = $value[] = $value['VesselName'];
$total = $value[] = $value['Total'];
$Box = $value[] = $value['Box'];
print_r($value); // print 2
$rdata .= '<td>'.$vname.'</td>
<td>'.$total.'</td>
<td>'.$Box.'</td>';
}
Print 1
Array
(
[VesselName] => MARIANNE
[Total] => 13838
[Box] => 1156
)
Array
(
[Box] => 154
)
Array
(
[Box] => 3825
)
Array
(
[Box] => 50571
)
print 2
Array
(
[VesselName] => MARIANNE
[Total] => 15452
[Box] => 1156
[0] => MARIANNE
[1] => 15452
[2] => 1156
)
Array
(
[Box] => 2276
[0] =>
[1] =>
[2] => 2276
)
Array
(
[Box] => 3825
[0] =>
[1] =>
[2] => 3825
)
Array
(
[Box] => 49235
[0] =>
[1] =>
[2] => 49235
)
i how can i remove an empty value in the array? i try many ways but i can get any solution.. so decide to here in the forum?
I'd try to reduce effort.
foreach ($this->CsInventory as $value)
{
foreach ($value as $key => $item)
{
$value[] = $item;
$rdata .= "<td>$item</td>";
}
print_r($value)
}
As a general comment, not sure why you're adding anonomous values back to the $values stack, might be better to use a different array.
If you have specific array elements you want to get rid of, you can use unset($array[$key]);
You could also prevent them getting into the array in the first place by using
if($value['VesselName']) {$vname = $value[] = $value['VesselName'];}
instead of simply
$vname = $value[] = $value['VesselName'];
function array_remove_empty($arr){
$narr = array();
while(list($key, $val) = each($arr)){
if (is_array($val)){
$val = array_remove_empty($val);
// does the result array contain anything?
if (count($val)!=0){
// yes :-)
$narr[$key] = $val;
}
}
else {
if (trim($val) != ""){
$narr[$key] = $val;
}
}
}
unset($arr);
return $narr;
}
array_remove_empty(array(1,2,3, '', array(), 4)) => returns array(1,2,3,4)