Sort multidimensional array secondary key - php

I'm trying to figure out the correct function in PHP to sort a multidimensional array. I considered doing a foreach and then using ksort (this didn't work). I think it might be useful to note that the secondary keys (the numeric ones) are "manually" set (instead of using array_push since the first key in that scenario would be 0 instead of 1).
This is for a single instance so I don't need a class for this or anything super-special, I'm interested in the correct-context function in PHP to make this bit of code more performance oriented (as well as to figure out what I'm doing wrong).
Note I want to keep the PRIMARY keys (e,g, Main and Promotional) their current order.
The unsorted array...
Array
(
[Main] => Array
(
[3] => Main2
[2] => Content
[1] => Main1
)
[Promotional] => Array
(
[3] => Promotional1
[2] => Content
[1] => Promotional2
)
)
The desired outcome (sorting by second-level key)...
Array
(
[Main] => Array
(
[1] => Main1
[2] => Content
[3] => Main2
)
[Promotional] => Array
(
[1] => Promotional2
[2] => Content
[3] => Promotional1
)
)

You may try:
foreach($array as $key => $data) {
ksort($data);
$array[$key] = $data;
}

You could also try this:
foreach($array as $key => &$data) {
ksort($data);
}
the ampersand before the $data variable indicates that the $data variable is a pointer, and any changes to that variable will cascade back to the original configuration.

Related

PHP foreach loop returns an extra unwanted array (Wikipedia API)

I've been researching this all day and haven't found any solutions. I'm also very new to php.
The purpose of my function is to take user input (Category1) of a Wikipedia article and return its categories. The basic function below does this without any problems.
function get_all_categories ( ) {
$url = $this->get_url ( 'categories' ) ;
$url .= 'titles='.urlencode($_POST['Category1']);
$url .= '&cllimit=500' ;
$data = $this->get_result ( $url ) ;
$array = json_decode($data, true); }
Example result for Urban planning:
Array
(
[batchcomplete] =>
[query] => Array
(
[pages] => Array
(
[46212943] => Array
(
[pageid] => 46212943
[ns] => 0
[title] => Urban planning
[categories] => Array
(
[0] => Array
(
[ns] => 14
[title] => Category:All Wikipedia articles written in American English
)
[1] => Array
(
[ns] => 14
[title] => Category:Commons category with local link same as on Wikidata
)
[2] => Array
(
[ns] => 14
[title] => Category:Pages using ISBN magic links
)
[3] => Array
(
[ns] => 14
[title] => Category:Urban planning
)
[4] => Array
(
[ns] => 14
[title] => Category:Use American English from April 2015
)
[5] => Array
(
[ns] => 14
[title] => Category:Use dmy dates from April 2015
)
[6] => Array
(
[ns] => 14
[title] => Category:Wikipedia articles needing clarification from June 2015
)
[7] => Array
(
[ns] => 14
[title] => Category:Wikipedia articles with GND identifiers
)
)
)
)
)
)
My problem begins when I try to extract from this array only the title values. I've attempted to do this with a foreach loop which is the easiest solution I found for multidimensional arrays:
$array1 = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array),
RecursiveIteratorIterator::SELF_FIRST);
foreach ($array1 as $key => $value) {
if (is_array($value) && $key == 'categories') {
$result = array_map(function($element){return $element['title'];}, $value);
print_r($result);
}
}
What I get with this code are two arrays. One array with only the titles (what I wanted), but also an unwanted array (sometime includes the first title) attached to the end:
Array
(
[0] => Category:All Wikipedia articles written in American English
[1] => Category:Commons category with local link same as on Wikidata
[2] => Category:Pages using ISBN magic links
[3] => Category:Urban planning
[4] => Category:Use American English from April 2015
[5] => Category:Use dmy dates from April 2015
[6] => Category:Wikipedia articles needing clarification from June 2015
[7] => Category:Wikipedia articles with GND identifiers
)
Array
(
[ns] =>
[title] => C
)
This extra array is what I don't understand. I think the problem is caused by the foreach loop. I tried unsetting $variable outside of the loop but it didn't help. The extra array becomes especially troublesome if I try to pass these results to another function. How can I prevent this from happening?
For simplicity you can traverse array manually rather than using RecursiveIteratorIterator.
RecursiveIteratorIterator will kill performance for large arrays.
Change your extracting logic to this:
$result = array();
foreach($arr['batchcomplete']['query']['pages'] as $k => $v)
{
foreach($v['categories'] as $cat)
{
$result[] = $cat['title'];
}
}
Working Demo
As #samir mentions, it would be faster to do it manually, but if you require a searching mechanism that traverses unknown depth, you can also use a basic recursive function. It might be a little faster than an OOP-style RecursiveArrayIterator/RecursiveIteratorIterator:
function recurse($array,&$new)
{
foreach($array as $key => $value) {
if($key == 'title' && isset($array['ns'])) {
if(!isset($array['pageid']))
$new[] = $value;
}
else {
if(is_array($value)) {
recurse($value,$new);
}
}
}
}
# Set's storage array for final titles
$new = array();
# Recurse your array
recurse($array,$new);
# Show stored values
print_r($new);
That's an interesting combination of PHP misfeatures:
$key == 'categories' is non-type-safe comparison; numeric array keys are integers, and for comparing an integer with a string PHP casts the string to an integer: roughly, it takes the longest prefix of the string which consists of numbers. If the string does not start with numbers at all, the result of the string to integer conversion is 0.So your condition will be true twice: for the categories subarray and for its first child (the one with the key 0). Tip: always use === for comparison.
PHP allows using the [] (array index) operator on almost anything that's not an array (usually returning null). So when the array_map tries to get $element['title'] for $element = 14 (the ns item of the first child of the categories subarray), that will succeed and result in null (which var_dump just displays as emptiness).
strings are slightly different: 'foo'[$n] is valid legacy syntax for getting the $n-th character of the string. When the array index operator is used on a string with a non-integer index, the index is cast to an integer (and as we have seen that usually results in zero). So 'Category:...'['title'] will result in the string 'C'.You should always be distrustful when using array index syntax on arrays with an unknown or unreliable structure, and use isset or something similar to make sure the array field you are trying to get exists.

Removing nth element from an array and reindex it

I have an array like below
Array
(
[0] => '13-Nov'
[1] => 'PUJA SUNUWAR'
[2] => '13-Nov'
[3] => '...301303'
[4] => 'TT1331600004\DLG'
[5] => '-10000.00'
[6] => '0'
[7] => '90000.00'
)
I need to remove 4th item of array and save it as
Array
(
[0] => '13-Nov'
[1] => 'PUJA SUNUWAR'
[2] => '13-Nov'
[3] => 'TT1331600004\DLG'
[4] => '-10000.00'
[5] => '0'
[6] => '90000.00'
)
i don't want to iterate over each elements of array. Is there any one shot function like array_pop to remove nth element of array?
use array_splice($array, 3, 1);
http://php.net/manual/en/function.array-splice.php
Is this a 2d-array? If so:
No, there is no built in function to do this. You could use ´array_walk´ with a custom callback but I doubt it would be faster than a simple foreach.
Else (if normal array):
unset( $aData[3] );
$aData = array_values( $aData );
Wich is faster then array_splice.
As mentioned above, there is no build in function for that.
You should use unset if you dont need to care about array indexing and array_values if should.
Also you should use value reference while array iterating to prevent internal array copyng while values modification. If dont, it can be one of perfomance break down reasons.
foreach ($yourDataSet as &$value) {
unset($value[2]);
//$value = array_values($value);
}
You shouldt use array_splice becouse of perfomance reasons.
p.s. Also you could check phpbench for perfomance test about different types of array iteration.

I want to add sub arrays to one single array keep id and value in php

My input array :
Array
(
[0] => Array
(
[id] => 1
[status_name] => Released
)
[1] => Array
(
[id] => 2
[status_name] => Under Construction
)
)
I want the output result :
Array (
[1] => Released
[2] => Under Construction
)
USe sub array id as output array key value and status_name as value array.
This is built into php as array_column. You would have:
$status_names = array_column($data, 'status_name', 'id');
print_r($status_name);
Bonus points on question as I had no idea this existed until looking for an answer for you.
Try the following:
function reOrderArray($input_array)
{
$result = array();
foreach ($input_array as $sub_array)
{
$result[$sub_array['id']] = $sub_array['status_name'];
}
return $result;
}
There might be a built-in php function to do this, array functions in php are quite powerful. I am, however, woefully unaware of one.

how do i print an element of an associative array when i dont know the key name

this array is generated and i want to be able to somehow grab the parent key without knowing the name, since i wont.
so the value i want is each array groups parent which would be zbench1, zbench2, .. and so on.
this array is already attached to a variable and i tried printing $myelements[0] but it gives an offset error.
Array
(
[zbench] => Array
(
[0] => editor-style.css
[1] => images
[2] => pagenavi-css.css
[3] => screenshot.png
[4] => style.css
)
[zbench1] => Array
(
[0] => editor-style.css
[1] => images
[2] => pagenavi-css.css
[3] => screenshot.png
[4] => style.css
)
[zbench2] => Array
(
[0] => editor-style.css
[1] => images
[2] => pagenavi-css.css
[3] => screenshot.png
[4] => style.css
)
[zbench3] => Array
(
[0] => editor-style.css
[1] => images
[2] => pagenavi-css.css
[3] => screenshot.png
[4] => style.css
)
)
You can get the values with array_keys().
foreach ($array as $key=>$value)
Or, if you have the key in a variable but don't a priori know what it is:
$array[$variable_holding_key]
Or if you just want to know what the keys are, but not necessarily do anything with them (all):
array_keys($array)
By definition, the inner arrays are only reachable via keys in the containing array - you have to know which parent key to use to access the appropriate child array. Is there a difference between each of those child arrays, other than having a slightly different parent key?
You can get all the keys in an array via array_keys(), which returns the keys as values in another array. Or you can use foreach($your_array as $key => $val) to iterate over each element in the array and get its associated key at the same time.
current() may work, it returns what the cursor is pointing to.
$element[key($element)]
array_shift, but this removes the last item.

Removing a value from a PHP Array

Using PHP I'm trying to remove an element from an array based on the value of the element.
For example with the following array:
Array
(
[671] => Array
(
[0] => 1
[1] => 100
[2] => 1000
)
[900] => Array
(
[0] => 15
[1] => 88
}
)
I'd like to be able to specify a value of on of the inner arrays to remove. For example if I specified 100 the resulting array would look like:
Array
(
[671] => Array
(
[0] => 1
[2] => 1000
)
[900] => Array
(
[0] => 15
[1] => 88
}
)
My first thought was to loop through the array using foreach and unset the "offending" value when I found it, but that doesn't seem to reference the original array, just the loop variables that were created.
Thanks.
foreach($array as $id => $data){
foreach($data as $index => $offending_val){
if($offending_val === 100){
unset($array[$id][$index]);
}
}
}
You can use:
array_walk($your_array, function(&$sub, $key, $remove_value) {
$sub = array_diff($sub, array($remove_value));
}, 100);
Couple of ideas:
You could try array_filter, passing in a callback function that returns false if the value is the one you want to unset. Using your example above:
$new_inner_array = array_filter($inner_array, $callback_that_returns_false_if_value_100)
If you want to do something more elaborate, you could explore the ArrayIterator class of the SPL, specifically the offsetUnset() method.

Categories