Currently working on a project in C but I have to generate a large struct which I figured would generate in PHP since I'm more familiar with PHP.
I have 2 arrays. The first one is quite simple (is way larger than this but I assume this is enough to replicate the issue):
$vehicles = [
'vehicleSuper' => [ "adder", "autarch", "banshee2", "bullet" ],
'vehicleSport' => [ "alpha", "banshee", "bestiagts", "blista2" ],
//...
];
The second array looks like this:
$textures = [
'candc_apartments' => [
"limo2_b", "limo2",
],
'candc_default' => [
"marshall_flag18_b", "mesa_b", "rentbus", "marshall_flag21_b", "crusader", "boxville4", "buzzard_b", "dukes2_b", "dukes",
],
'lgm_default' => [
"hotknife", "coquette", "voltic_tless", "vacca", "infernus", "cogcabri_b", "stinger_b", "banshee_b", "ztype", "ninef", "jb700", "superd", "monroe_b", "rapidgt2_b", "khamel", "comet2_b", "cheetah_b", "rapidgt_b", "stinger", "carbon_b", "surano_convertable_b", "rapidgt2", "infernus_b", "jb700_b", "ninef_b", "stingerg", "superd_b", "bullet_b", "ztype_b", "hotknife_b", "cogcabri", "surano_convertable", "rapidgt", "stingerg_b", "coquette_b", "bullet", "carbon", "ninef2", "carboniz", "cheetah", "adder_b", "entityxf", "adder", "feltzer",
],
];
Now I generate the list like this using the 2 arrays above:
echo '<pre>';
foreach($vehicles as $category => $val) {
echo "vehicleSpawner " . $category . "[] = {\n";
foreach($val as $item) {
echo " { \"" . $item . "\", \"" . array_search($item, array_column($textures, $item)) . "\", \"\" },\n";
}
echo '}';
echo '<hr>';
}
This outputs something similar to:
{ "adder", "", "" },
The last 2 values are empty. What I want to achieve: Fill these out with the values from $textures array. In this case, I'm trying to fill it up like this:
// arg 1: name from $vehicles
// arg 2: key from $textures
// arg 3: val from $textures
{ "adder", "lgm_default", "adder" },
Currently my array_search($item, array_column($textures, $item)) method doesn't seem to work. How would I go and get this working? Help is appreciated, thanks all!
array_column($textures, $item) will search in array $textures key named $item, but there is no key with that name so it returns false, what you need to do is loop on $textures array and search if value $item exists:
foreach($val as $item) {
foreach($textures as $k => $v) {
//this will return array index or false if not exists
$pos = array_search($item, $v);
if ( $pos !== false )
echo " { \"" . $item . "\", \"" . $k . "\", \"".$v[$pos]."\" },\n";
}
}
If you want to see multiple matches within a given pair of subarrays, array_intersect() will compare both subarrays once and iterate the results. This is more efficient than running fresh array_search() calls for each element of one of the subarrays.
Code: (Demo)
foreach($vehicles as $category => $v_vals) {
echo "vehicleSpawner " . $category . "[] = {\n";
foreach($textures as $k => $t_vals) {
foreach (array_intersect($v_vals, $t_vals) as $match) {
echo " { \"$match\", \"$k\", \"$match\" },\n";
}
}
echo "}\n";
}
Output:
vehicleSpawner vehicleSuper[] = {
{ "adder", "lgm_default", "adder" },
{ "bullet", "lgm_default", "bullet" },
}
vehicleSpawner vehicleSport[] = {
}
If this isn't the exact output format/structure that you desire, it can be tweaked to accommodate.
Related
I have the following JSON Data:
{
"tables": [
{
"name": "PrimaryResult",
"columns": [
{
"name": "TimeGenerated",
"type": "datetime"
},
{
"name": "Computer",
"type": "string"
}
],
"rows": [
[
"2022-12-03T21:58:48.519866Z",
"DESKTOP-KAFCPRF"
],
[
"2022-12-03T21:58:48.5198773Z",
"DESKTOP-KAFCPRF"
]
]
}
]
}
I'm using this to and trying to find a way to parse the columns as tables headers(TH) and the row data as(TR).
This is what I have:
$jsonObjs = json_decode($data, true);
echo "<pre>" . var_dump($jsonObjs) . "</pre>";
foreach($jsonObjs as $a){
foreach($a[0] as $b) {
foreach($b[1] as $key => $value){
echo $key . " : " . $value . "<br />";
}
}
}
but my results are coming up like:
name : Computer
type : string
0 : 2022-12-03T21:58:48.5198773Z
1 : DESKTOP-KAFCPRF
Here is a loop that will go through the columns and rows. From here it's fairly simple to adjust the logic for building a table. If you need any further help, let me know.
foreach($jsonObjs["tables"] as $a)
{
// Columns
foreach($a["columns"] as $key => $value)
{
$cName = $value["name"];
$cType = $value["type"];
echo("Column name is: ".$cName);
echo("Column type is: ".$cType);
}
// Rows:
foreach($a["rows"] as $key => $value)
{
$rValue1 = $value[0];
$rValue2 = $value[1];
echo("Row: " . $rValue1 . " | " . $rValue2);
}
}
I have a multidimensional array.
$tree= [
"wood"=> [
"segun",
"koroi",
"karosin"
],
"food"=> [
'grain',
"vegetable"=> [
"potato",
"tomato"=>[
"small"=>["cherri","local"],
"big"=>["green","red"]
],
"radish"
],
"fruits"=> [
"mango"=>[
"lengra",
"amrupali",
"fozli",
"him sagar"
],
"jak fruits"
]
],
"medicine"=> [
"nim",
"arjun",
"amla"
],
"oxygen",
"computer"
];
I am using this code to show
function treeView($tree){
$markup='';
foreach ($tree as $key=>$value){
$markup.= '<li>'. (is_array($value) ? $key. treeView($value) : $value) .'</li>';
}
return "<ul>".$markup."</ul>";
}
I want to show upto 2 nodes of each element. This is not fixed, it can be nth nodes depends on user input. I am not getting it how to solve this.
If user input 3, I would like show the output like this
If user input 2, I would like show the output like this
Just add an optional "defaults to 0" level parameter.
function treeView($tree, $max_level = 2, $current_level = 0)
{
if ($max_level == $current_level) {
return "";
}
$markup = '';
foreach ($tree as $key => $value) {
$markup .= '<li>' . (is_array($value) ? $key . treeView($value, $max_level, $current_level + 1) : $value) . '</li>';
}
return "<ul>" . $markup . "</ul>";
}
I am trying to parse a json array string. Though print_r prints all the values properly but while fetching the records I failed.
I must be doing something very terribly wrong. Could you please help to correct it.
So here is my code
<?
$str ='
{
"tenant_view_details": [
{
"status":"S",
"tenant_general":[
{"tenant_id":"6003","code":"ICI001","type":"BANK","category":"SM","gstn":"IWSDFS7372","pan":"KSAH9876AS","cin":"ASHED456","name":"ICICI Bank","address_line_1":"23, Hertz Plaza, Rajiv Chowk","address_line_2":" ","address_city":"New Delhi","address_distict ":"New Delhi","address_state ":"DL","address_state_code ":"07","address_pin ":"119923","contact_name ":"contact_name","contact_phone ":"1234567890","contact_std_code ":"11","contact_landline ":"1234567890","contact_email_id ":"contact#email.com"} ],
"tenant_bank": [
{ "bank_name ":"xyz","bank_account_no ":"12345","account_type ":"abc","ifsc_code ":"xx123","address_line_1 ":"qwer","address_line_2 ":"23","address_city ":"abc","address_district ":"xyz","address_state_name ":"asd","address_state_code ":"02","address_pin ":"123456" } ],
"tenant_agreement": [
{ "category ":"OM","tenancy_type ":"EXT","echarge_type ":"FIX","total_tenancy_value ":"32900.00","energy_charge_value ":"16543.00","rev_share_pct ":"0.05","start_dt":"10-1-2018","end_dt":"31-12-2020","attachment_path ":"na","change_value ":"na","latest_flag ":"Y","w_status ":"20","status ":"ACT"} ],
"tenant_sites": [
{"tenant_id":"6003","site_master_id":"1020","tn_site_code":"UPWMORA00069473","tn_site_name":"Deendayal Nagar","tn_cluster":"CLUSTER-03","circle_code":"UW","tower_type":"MAST","site_type":"ID","tenancy_type":"EXT","echarge_type":"FIX","primary_tenant":"N","latest_flag ":"Y"}, {"tenant_id":"6003","site_master_id":"1019","tn_site_code":"UPWGHAZ00069467","tn_site_name":"DJ College Newari Road, Modina","tn_cluster":"CLUSTER-03","circle_code":"UW","tower_type":"MAST","site_type":"ID","tenancy_type":"EXT","echarge_type":"FIX","primary_tenant":"N","latest_flag ":"Y"}, {"tenant_id":"6003","site_master_id":"1018","tn_site_code":"UPWMORA00069464","tn_site_name":"Bazar Makhbra","tn_cluster":"CLUSTER-03","circle_code":"UW","tower_type":"RTT","site_type":"OD","tenancy_type":"EXT","echarge_type":"FIX","primary_tenant":"N","latest_flag ":"Y"}, {"tenant_id":"6003","site_master_id":"1016","tn_site_code":"UPWGHAZ00069454","tn_site_name":"Hoshdarpur Garhi","tn_cluster":"CLUSTER-03","circle_code":"UW","tower_type":"RTT","site_type":"OD","tenancy_type":"EXT","echarge_type":"FIX","primary_tenant":"N","latest_flag ":"Y"}, {"tenant_id":"6003","site_master_id":"1011","tn_site_code":"UPWMUZN00069430","tn_site_name":"Sikanderpur","tn_cluster":"CLUSTER-03","circle_code":"UW","tower_type":"RTT","site_type":"ID","tenancy_type":"EXT","echarge_type":"FIX","primary_tenant":"N","latest_flag ":"Y"}, {"tenant_id":"6003","site_master_id":"1008","tn_site_code":"UPWALIG00069299","tn_site_name":"Mukund Vihar","tn_cluster":"CLUSTER-03","circle_code":"UW","tower_type":"RTT","site_type":"","tenancy_type":"EXT","echarge_type":"FIX","primary_tenant":"N","latest_flag ":"Y"} ]
}
]
}
';
$dataset = json_decode($str, true);
//print_r ($dataset);
foreach ($dataset['tenant_view_details'] as $newdata) {
$general = $newdata['tenant_general'];
$bank = $newdata['tenant_bank'];
$agreement = $newdata['tenant_agreement'];
$sites = $newdata['tenant_sites'];
}
//prinitng data
echo "<br/>";
print_r($general);
echo "<br/>";
print_r($bank);
echo "<br/>";
print_r($agreement);
echo "<br/>";
foreach($general as $general_data){
(isset($general_data['tenant_id']) && !empty($general_data['tenant_id']))? $tenant_id=$general_data['tenant_id'] : $tenant_id="not set";
echo "<br/>tenant_id::" . $tenant_id;
}
foreach($bank as $bank_data){
(isset($bank_data['bank_name']) && !empty($bank_data['bank_name']))? $bank_name=$bank_data['bank_name'] : $bank_name="not set";
echo "<br/>bank_name:" . $bank_data['bank_name'];
}
foreach($agreement as $agreement_data){
(isset($agreement_data['category']) && !empty($agreement_data['category']))? $category=$agreement_data['category'] : $category="not set";
(isset($agreement_data['tenancy_type']) && !empty($agreement_data['tenancy_type']))? $tenancy_type=$agreement_data['tenancy_type'] : $tenancy_type="not set";
(isset($agreement_data['echarge_type']) && !empty($agreement_data['echarge_type']))? $echarge_type=$agreement_data['echarge_type'] : $echarge_type="not set";
echo "<br/>category:" . $category;
echo "<br/>tenancy_type:" . $tenancy_type;
echo "<br/>echarge_type:" . $echarge_type;
}
?>
Your problem is that in your $bank and $category arrays, all the keys have trailing spaces on them. If you change the references to include those spaces, your code works fine. See https://3v4l.org/GX5iC
Alternatively you can trim the array keys, using something like this code inside your foreach loops:
$bank_keys = array_map('trim', array_keys($bank_data));
$bank_data = array_combine($bank_keys, array_values($bank_data));
You could also create a recursive function to trim the entire $dataset value. For example:
function trim_keys($array) {
foreach ($array as $key => $value) {
echo "trimming key '$key' to '" . trim($key) . "'\n";
unset($array[$key]);
$array[trim($key)] = $value;
if (is_array($value))
$array[trim($key)] = trim_keys($value);
else
$array[trim($key)] = $value;
}
return $array;
}
Then, by using
$dataset = trim_keys($dataset);
Your code will work fine. Demo on 3v4l.org
I have written a code, that finds value in second array if it finds specific key from first array, but my question is - is it possible to do it better? for example without 3 loops ?
For example here are keys and values to search for, which user has checked at form and submitted ($tegoszukamy):
array (
'kolor' =>
array (
0 => 'bialy',
1 => 'zielony',
),
'rozmiar' =>
array (
0 => '60',
1 => '70',
),
'rozdzielczość' =>
array (
0 => '1200x1800',
),
'moc' =>
array (
0 => '500W',
),
);
Here is array with products IDs where searching is performed ($tuszukamy):
array (
47 =>
array (
'rozmiar' => '50,60,70,80,90,100',
'kolor' => 'bialy,czarny',
),
48 =>
array (
'rozmiar' => 'L,M,XS,S,L',
'kolor' => 'zielony,niebieski,czerwony,zolty,bialy,czarny',
),
49 =>
array (
'rozdzielczość' => '1200x1800',
'prędkość' => '60str/min',
)
)
Here is my code that is working fine:
foreach ($tegoszukamy as $atrybut=>$wartosci_szukane) {
foreach ($tuszukamy as $numer_posta=>$wartosci_zbioru ) {
if (array_key_exists($atrybut, $wartosci_zbioru) !== FALSE){
foreach ($wartosci_szukane as $ws) {
if (strpos($wartosci_zbioru[$atrybut],$ws) !== FALSE) {
echo
'We have found'
.$ws.
'in'
.$wartosci_zbioru[$atrybut].
'where product id is'
.$numer_posta.
''
;}
else {
echo
'We found not'
.$ws.
'in'
.$wartosci_zbioru[$atrybut].
''
;}
}
}
}
}
Is it possible to do it better/with better code performance/speed, because I dont know if these 3 loops will be good when user filters through eg. 10000 products.
I came up with the following alternatives:
1.
class Subject {
private $attr_name;
private $attr_values;
function __construct($attr_name, $attr_values) {
$this->attr_name = $attr_name;
$this->attr_values = $attr_values;
}
public function check($key, $item) {
$found = array();
if (isset($item[$this->attr_name])) {
foreach($this->attr_values as $val) {
strstr($item[$this->attr_name], $val) && array_push($found, $val);
}
}
count($found) > 0 ?
$message = "Found attribute <u>" . $this->attr_name . "</u> with value <b>" . implode(", ", $found) . "</b> in ID: " . $key . "."
:
$message = "No matches for <u>" . $this->attr_name . "</u> found in ID: " . $key;
return $message;
}
}
foreach ($tegoszukamy as $attr_name=>$attr_values) {
$filtered = array_map(array(new Subject($attr_name, $attr_values), "check"), array_keys($tuszukamy), $tuszukamy);
foreach($filtered as $result) {
echo $result . '<br>';
}
}
2.
foreach ($tegoszukamy as $attr_name=>$attr_values) {
$filtered = array_filter($tuszukamy, function ($item, $key) use($attr_name, $attr_values) {
$found = array();
if (isset($item[$attr_name])) {
// var_dump($item[$attr_name]);
foreach($attr_values as $val) {
strstr($item[$attr_name], $val) && array_push($found, $val);
}
}
count($found) > 0 ?
$message = "Found attribute <u>" . $attr_name . "</u> with value <b>" . implode(", ", $found) . "</b> in ID: " . $key . "."
:
$message = "No matches for <u>" . $attr_name . "</u> found in ID: " . $key;
echo $message . "<br>";
return count($found) > 0;
}, ARRAY_FILTER_USE_BOTH);
// something to do with $filtered;
}
I'm not sure whether either of them is faster than yours. I'll leave the testing to you. :)
The first one was inspired by jensgram's answer to this question: PHP array_filter with arguments
I have an associative array. Two dimensions which I am iterating through like this
foreach ( $order_information as $sector_index => $sector_value ){
echo 'sector : ' . current($order_information) ;
echo '<br>';
foreach ( $sector_value as $line_index => $line_value ){
}
}
The current() is an attempt to get the iteration the loop is in. It seems like this should give me that. However, elsewhere on that page there is the suggestions that you just do like
$index = 0
foreach ( $array as $key => $val ) {
echo $index;
$index++;
}
I wonder if I am using current incorrectly, as echo 'sector : ' . current($order_information); just prints sector : Array
Is $index++ bad syntax? Is there a better way to do this?
Answer
As far as I know there is no build in numeric counter in a foreach loop in PHP.
So you need your own counter variable. Your example code looks quite good to do that.
$index = 0;
foreach($array as $key => $val) {
$index++;
}
By the way, $index++; is fine.
Example
Here is an example illustrating which variable stores which value.
$array = array(
"first" => 100,
"secnd" => 200,
"third" => 300,
);
$index = 0;
foreach($array as $key => $val) {
echo "index: " . $index . ", ";
echo "key: " . $key . ", ";
echo "value: " . $val . "\n";
$index++;
}
The output will be that.
index: 0, key: first, value: 100
index: 1, key: secnd, value: 200
index: 2, key: third, value: 300
Current-Function
I think you misunderstood current($array). It gives you the value pointed by an internal array pointer, which can be moved using next($array), prev($array) and end($array).
Take a look at the manual to make thinks clear.