I have been playing around with array_search. I have been trying to search an array and get details from it. The problem is, once it finds the result it moves on, it doesn't check for duplicates in the array. I can't seem to work out my loop logic, any suggestions?
The $names array
Array(
[0] => Array
(
[name] => Fred
[age] => 20
)
[1] => Array
(
[name] => George
[age] => 17
)
[2] => Array
(
[name] => Sarah
[age] => 22
)
[3] => Array
(
[name] => Fred
[age] => 30
)
)
$name=" Fred";
//loop here
$array_position = array_search($name, array_column($names, 'name'));
$array_data = $names[$array_position];
echo $array_data['name'] . " is: " . $array_data['age'] . " years old.
//end loop
Result:
Fred is 20 years old.
Expected result:
Fred is 20 years old
Fred is 30 years old.
I tried array_keys() but I don't understand php.net very well
Should I try store the results in a separate array and then loop that to print? Seems like there should be a more efficient/elegant solution.
use array_filter to find all.
function search($array, $key)
{
return array_filter($array, function($v) use($key){return $v['name'] == $key;});
}
$result = search($array, $key);
foreach($result as $v)
{
echo $v['name'] . " is: " . $v['age'] . " years old.";
}
#Ben first of all array_search() return true or false not the key, but for your desired output you can simply try with foreach() with a condition like below or with array_key:
with foreach()
<?php
$names = array(0 =>
array(
"name" => "Fred",
"age" => 20
),
1 => array(
"name" => "George",
"age" => 17
),
2 => array(
"name" => "Sarah",
"age" => 22
),
3 => array(
"name" => "Fred",
"age" => 30
)
);
$name= "Fred";
echo "<pre>";
foreach($names as $val){
if($val["name"] == $name){
echo $name . " is: " . $val["age"] . " years old.\n";
}
}
with array_key()
<?php
$names = array(0 =>
array(
"name" => "Fred",
"age" => 20
),
1 => array(
"name" => "George",
"age" => 17
),
2 => array(
"name" => "Sarah",
"age" => 22
),
3 => array(
"name" => "Fred",
"age" => 30
)
);
$name=" Fred";
$array_position = array_keys(array_column($names, "name"), "Fred");
foreach($array_position as $key){
echo $names[$key]["name"] . " is: " . $names[$key]["age"] . " years old.\n";
}
OUTPUT:
Fred is: 20 years old.
Fred is: 30 years old.
What's wrong with a simple foreach loop?
// Declare the array
$names = array(
array(
'name' => 'Fred',
'age' => 20
),
array(
'name' => 'George',
'age' => 17
),
array(
'name' => 'Sarah',
'age' => 22
),
array(
'name' => 'Fred',
'age' => 30
)
);
// Name to search
$name = 'Fred';
foreach($names as $index => $data){
if($data['name'] == $name)
echo $data['name'] . ' is ' . $data['age'] . ' years old.<br>';
}
And the result would be:
Fred is 20 years old.
Fred is 30 years old.
array_keys() can do this:
<?php
$names = array(
array(
'name' => 'Fred',
'age' => 20
),
array(
'name' => 'George',
'age' => 17
),
array(
'name' => 'Sarah',
'age' => 22
),
array(
'name' => 'Fred',
'age' => 30
)
);
$matchKeys = array_keys( array_column($names, 'name'), 'Fred' );
array_map(function($arrKey) use ($names) {
echo $names[$arrKey]['name'] . " is: " . $names[$arrKey]['age'] . " years old.\n";
}, $matchKeys);
Result:
Fred is: 20 years old.
Fred is: 30 years old.
Array(
[0] => Array
(
[name] => Fred,
[age] => 20
),
[1] => Array
(
[name] => George,
[age] => 17
),
[2] => Array
(
[name] => Sarah,
[age] => 22
),
[3] => Array
(
[name] => Fred,
[age] => 30
)
)
$name="Fred";
//loop here
for($i =0; i<count($names); $i++){
if($arr[$i] == $name)echo $name . ' is ' . $names[$i] ."years old.<br>";
}
//end loop
Output:
Fred is 20 years old
Fred is 30 years old
This can help -
$check_name= 'Fred'; // set the name to check
$temp= array_filter($names, function($a) use($check_name) {
return $a['name'] === $check_name; // return if matches
});
// loop through the result
foreach($temp as $v) {
echo $v['name'] . ' is ' . $v['age'] . ' years old.<br>';
}
Output
Fred is 20 years old.
Fred is 30 years old.
Working code
Anonymous function & use keyword
I dont understand why you gave space in $name variable
$name = " Fred";
Here is your code,
$name=" Fred";
function array_search_custom($needle,$haystack) {
$temp = [];
foreach($haystack as $key=>$value) {
if(trim($needle)===trim($value)) {
$temp[] =$key;
}
}
return $temp;
}
$name=" Fred";
$a_names = array_column($names, 'name');
$a_ages = array_column($names, 'age');
$array_position = array_search_custom($name, $a_names);
foreach($a_names as $k => $v){
if($array_position && in_array($k, $array_position)){
echo $a_names[$k] . " is: " . $a_ages[$k] . " years old.<br/>";
}
}
I trimmed your name and wrote custom array search function as per your requirement.
Give it a try, it will work.
Related
I have an array of players each with a number of points.
I can easily sort the array in order of the points using a custom usort function.
But when two players have the same amount of points I need to rank them as the same winning position within the list.
E.g.
Nick - 25
Tom - 18
Chris - 18
Dave - 16
James - 8
In this case the data that I require would be
Nick - 1st
Tom - (joint) 2nd
Chris - (joint) 2nd
Dave 3rd
James 4th
So players with equal scores are designated the same ranking position.
What is the best way of calculating these positions?
Thanks!
This will give you what you want with an additional fix: if you have two players in position 2 the next player should be in position 4. If you don't want this additional fix move $count++; into the if statement.
$count = 0;
$position = 0;
$last_score = -1;
foreach ($players as $player)
{
$count++;
if ($last_score !== $player->score)
{
$position = $count;
}
$player->position = $position;
$last_score = $player->score;
}
I think the following code would do the job as required:
$scores = array('Nick'=>25,'Tom'=>18,'Chris'=>18,'Dave'=>16, 'James'=> 8,);
$scores_numbers = array_unique(array_values($scores));
$scores_counter = array_count_values($scores);
$pos = 1;
foreach($scores_numbers as $num) {
foreach($scores as $name=>$score) {
if($num == $score) {
if($scores_counter[$score] > 1) {
echo "$name - (joint) $pos<br />";
} else {
echo "$name - $pos<br />";
}
}
}
$pos++;
}
I have updated the code to avoid the duplicating output.
If you are retrieving player stats from DB then below code can be useful to rank them :
<?php
$players = [
['name' => 'Ash',
'point' => 0
],
['name' => 'Bob',
'point' => 10
],
['name' => 'Cane',
'point' => 0
],
['name' => 'Dory',
'point' => 6
],
['name' => 'Efat',
'point' => 6
],
];
usort($players, function($v1, $v2){
return $v2['point'] - $v1['point'];
});
$ranking = [];
$currentPosition = 0;
$heighestPoint = PHP_INT_MIN;
foreach($players as $player){
if($heighestPoint !== $player['point']){
$currentPosition++;
$heighestPoint = $player['point'];
}
$ranking[$currentPosition][] = $player;
}
print_r($ranking);
Output :
Array
(
[1] => Array
(
[0] => Array
(
[name] => Bob
[point] => 10
)
)
[2] => Array
(
[0] => Array
(
[name] => Dory
[point] => 6
)
[1] => Array
(
[name] => Efat
[point] => 6
)
)
[3] => Array
(
[0] => Array
(
[name] => Ash
[point] => 0
)
[1] => Array
(
[name] => Cane
[point] => 0
)
)
)
May it helps
/*Below array must be sorted */
$a1=array("Nick"=>25,"Tom"=>18,"Chris"=>18,"Dave"=>16,"James"=>8);
$makeUnique=array_unique($a1);
$makeUnique=array_values($makeUnique);
$pArr=array_map('setPosition',$a1);
print_r($pArr);
function setPosition($a){
Global $makeUnique;
return array_search($a,$makeUnique)+1;
}
OUT PUT
Array ( [Nick] => 1 [Tom] => 2 [Chris] => 2 [Dave] => 3 [James] => 4 )
I used usort to sort assoc array
$players = [["name" => "Nick" , "score" => 25] , ["name" => "Tom" , "score" => 18] , ["name" => "chris" , "score" => 18] , ["name" => "dave" , "score" => 16 ] , ["name" => "james" , "score" => 8]];
usort($players , function($a , $b) {return $b["score"] - $a["score"];} );
var_dump($players);
$lastScore = null;
$pos = 1;
foreach($players as $player)
{
if($lastScore != null && $lastScore == $player["score"])
echo $pos-1 . " - " . $player["name"] . '<br/>';
else
echo $pos++ . " - " . $player["name"] . '<br/>';
$lastScore = $player["score"];
}
checkout this code in teh playground
I would like to edit database entries with a simple form.
The id and name of each entry is fixed.
Problems:
After submitting the form $farray does only include the edited data of $array[3] not of the other records.
$farray doesn't include name and id (not included in the form). I need the id of the record for the query.
What could I use as a workaround?
Current script
<?php
$query = mysql_query("SELECT * FROM database");
$array = array();
while($row = mysql_fetch_assoc($query)){
$array[] = $row;
}
if(isset($_POST['send']))
{
$farray = $_POST['farray'];
foreach ($farray as $key => $value) {
echo('UPDATE database SET ' . $key . ' = "' . $value . '"' . ' WHERE id = ' . $farray['id']); //testing
}
}
?>
<form action=" <?=$_SERVER['PHP_SELF']?> " method="POST">
<?php
foreach($array as $key1){
echo $key1["name"] . "<br />";
foreach($key1 as $key => $value){
if ($key != "id" AND $key != "name") {
print $key.
' <input type="text" name="farray['.$key.']" value="'.$value.'"><br /><br />';
}
}
}
?>
<input type="submit" name="send" value="send">
</form>
Example $array
Array
(
[0] => Array
(
[id] => 0
[name] => name0
[1] => 1
[2] => 2
[3] => 3
)
[1] => Array
(
[id] => 1
[name] => name1
[1] => 1
[2] => 2
[3] => 3
)
[2] => Array
(
[id] => 2
[name] => name2
[1] => 1
[2] => 2
[3] => 3
)
[3] => Array
(
[id] => 3
[name] => name3
[1] => 1
[2] => 2
[3] => 3
)
)
Example $farray (after editing and submitting form)
Array
(
[1] => 10
[2] => 20
[3] => 30
)
OK, even though your table fields are not 1, 2, and 3, you just needed to change up your posted array a little. So I made you a little example:
<form method="post">
<?php
// Simulate DB records
$array = [
[
'id' => 0,
'name' => 'name0',
'1' => 1,
'2' => 2,
'3' => 3
],
[
'id' => 1,
'name' => 'name1',
'1' => 1,
'2' => 2,
'3' => 3
],
[
'id' => 2,
'name' => 'name2',
'1' => 1,
'2' => 2,
'3' => 3
]
];
// Create the input fields:
foreach( $array as $key1 )
{
echo $key1["name"] . "<br />";
foreach($key1 as $key => $value)
{
if ($key != "id" AND $key != "name")
{
echo $key.
' <input type="text" name="farray[' . $key1['id'] . ']['.$key.']" value="'.$value.'"><br /><br />';
}
}
}
?>
<button type="submit">Submit</button>
</form>
<pre>
<?php
if( isset( $_POST['farray'] ) )
{
print_r( $_POST );
foreach( $_POST['farray'] as $id => $values )
{
foreach( $values as $k => $v )
{
echo('UPDATE database SET ' . $k . ' = "' . $v . '"' . ' WHERE id = ' . $id ) . '<br />';
}
}
}
?>
</pre>
I tested this, and I think it works as you would expect.
Array
(
[0] => Array
(
[intID] => 3
[intVolumeType] => 1
[intVolume] => 10
[totalVolumes] => 10
[intTrack] => 10
[intTrackType] => 2
[totalTracks] => 10
)
[1] => Array
(
[intID] => 4
[intVolumeType] => 2
[intVolume] => 100
[totalVolumes] => 200
[intTrack] => 111
[intTrackType] => 3
[totalTracks] => 222
)
)
I want to print above array as:
intVolumeType = 1
totalVolumes = 10
intVolumeType = 2
totalVolumes = 200
intTrackType = 2
totalTracks = 10
intTrackType = 3
totalTracks = 222
How to loop through this PHP array. There are total six elements in array. Which might increase upto 20. Print first Volume Information, than Track, and so on.Please help
try this here: http://phpfiddle.org/
<?php
$a = Array
(
0 => [
'intID' => 3,
"intVolumeType" => 1,
"intVolume" => 10,
"totalVolumes" => 10,
"intTrack" => 10,
"intTrackType" => 2,
"totalTracks" => 10,
],
1 => [
"intID" => 4,
"intVolumeType" => 2,
"intVolume" => 100,
"totalVolumes" => 200,
"intTrack" => 111,
"intTrackType" => 3,
"totalTracks" => 222,
]
);
/*echo "<pre>";
print_r( $a );
echo "</pre>";
*/
// you have to do it manually
$volume = "";
$track = "";
foreach ( $a as $item ) {
// preparing for volumes types
$volume .= "intVolumeType = " . $item['intVolumeType'] . "<br/>";
$volume .= "TotalVolumes = " . $item['totalVolumes'] . "<br/>";
// you can add other variables too
$volume .= "<br/>";
// preparing for track types
$track .= "intTrackType = " . $item['intTrackType'] . "<br/>";
$track .= "TotalTracks = " . $item['totalTracks'] . "<br/>";
// you can add other variables too
$track .= "<br/>";
}
echo $volume;
echo "===================<br/>";
echo $track;
?>
I have array like below:
Array
(
[22] => Array
(
[0] => 60
[29] => Array
(
[0] => 6
)
[30] => Array
(
[0] => 5
[1] => 8
)
[31] => Array
(
[0] => 7
[1] => 9
[2] => 14
[3] => 26
)
)
[23] => 12
[35] =>10
[42] =>22
)
now i want to implode array like
60[6][5||8][7||9||14||26]|12|10|22
I have tried below code:
$arr = array_map(function($el){ return $el['tag_id']; }, $arr);
$str = implode(',', $arr);
But it is not implode with required glue
How can i do it?
you can use this code
<?php
$a= Array(
22 => Array(
0 => 60,
29 => Array(
0 => 6
),
30 => Array
(
0 => 5,
1 => 8
),
31 => Array
(
0 => 7,
1 => 9,
2 => 14,
3 => 26
),
),
23 => 12,
35 =>10,
42 =>22,
);
$string='';
foreach($a as $arr){
if(is_array($arr)){
foreach($arr as $array){
if(is_array($array)){
$string .= '['.implode("||",$array).']';
}else{
if($string!==''){ $string .= '|';}
$string .= $array;
}
}
}else{
if($string!==''){ $string .= '|';}
$string .= $arr;
}
}
echo $string;die;
?>
Out put wil be
60[6][5||8][7||9||14||26]|12|10|22
Desired result without foreach.
$array = [
22 => [
0 => 60,
29 => [
0 => 6
],
30 => [
0 => 5,
1 => 8
],
31 => [
0 => 7,
1 => 9,
2 => 14,
3 => 26
]
],
23 => 12,
35 => 10,
42 => 22
];
$result = implode('|', array_map(function($item)
{
return is_array($item) // convert sub array into string
? implode('', array_map(function($inner_item)
{
return is_array($inner_item) // convert inner array into string
? '[' . implode('||', $inner_item) . ']'
: $inner_item;
}, $item))
: $item;
}, $array));
var_dump($result);
So, we have 3 types of delimiters: '|' - first level, ''(empty) - second level, '||' - third level.
You can use foreach and implode to achieve your pattern:
<?php
header('Content-Type: text/plain');
$arr = array();
$arr22 = array();
$arr22[0] = 60;
$arr22[29] = array(6);
$arr22[30] = array(5,8);
$arr22[31] = array(7,9,14,26);
$arr[22] = $arr22;
$arr[23] = 12;
$arr[35] = 10;
$arr[42] = 22;
$output = '';
foreach($arr as $entry) {
if(!is_array($entry)) {
$output .= $entry;
} else {
// array
foreach($entry as $inner) {
if(is_array($inner)) {
$output .= '[' . implode('||', $inner) . ']';
} else {
$output .= $inner;
}
}
}
$output .= '|';
}
echo substr($output, 0, strlen($output) - 1);
?>
which outputs:
60[6][5||8][7||9||14||26]|12|10|22
This should work for you:
Here the glue is configurable as you desired and this logic is built on the recursive call hence this will work for any level of multidimensional array:
<?php
$arrVal = array (
'22' => array(
'0' => 60,
'29' => array(
'0' => 6
),
'30' => array (
'0' => 5,
'1' => 8
),
'31' => array (
'0' => 7,
'1' => 9,
'2' => 14,
'3' => 26
)
),
'23' => 12,
'35' => 10,
'42' => 22
);
//60[6][5||8][7||9||14||26]|12|10|22
$constructedValue = "";
$glue = "||";
echo $constructedValue = implodeMultiArr($arrVal,$glue);
function implodeMultiArr($arrVal,$glue) {
$i = 0;
$constructedValue = "";
foreach ( $arrVal as $k=>$v) {
if ( is_array($v) ) {
$constructedValue .= !empty($constructedValue) ? "[".implodeMultiArr($v,$glue)."]" : implodeMultiArr($v,$glue)."]" ;
} else {
$constructedValue .= !empty($constructedValue) ? $glue.$v : $v ;
}
$i++;
}
return $constructedValue;
}
i have this data
[0] => 1#*#1-1
my requirement is explode from #*# and have to make generated array elements as key value pairs
Example
$data = explode("#*#",'1#*#1-1');
$data[0] =1;
$data[1] = 1-1;
now my requirement is make a dynamic associative array
array($data[1] => $data[0])
<?
$str = '1#*#1-1
3#*#1-2
5#*#1-3
7#*#1-4
9#*#1-5
11#*#1-6
13#*#1-7
15#*#1-8
17#*#1-9
19#*#1-10
2#*#2-1
4#*#2-2
6#*#2-3
8#*#2-4
10#*#2-5
12#*#2-6
14#*#2-7
16#*#2-8
18#*#2-9';
$ex = array_map('trim',explode("\n",$str));
$out = array();
foreach($ex as $e){
$ex2 = explode('#*#',$e);
$out[$ex2[1]] = $ex2[0];
}
print_r($out);
Array
(
[1-1] => 1
[1-2] => 3
[1-3] => 5
[1-4] => 7
[1-5] => 9
[1-6] => 11
[1-7] => 13
[1-8] => 15
[1-9] => 17
[1-10] => 19
[2-1] => 2
[2-2] => 4
[2-3] => 6
[2-4] => 8
[2-5] => 10
[2-6] => 12
[2-7] => 14
[2-8] => 16
[2-9] => 18
)
?>
<?php
$mydata = array();
$data = array('1#*#1-1');
list($key, $val) = explode('#*#', $data[0]);
$mydata[$val] = $key;
// Check work.
echo '<pre>' . print_r($mydata, TRUE) . '</pre>';