I am trying to push 2 variables into an array but I want that the key is the same.
The code below is a search function through a folder full of files.
In the foreach, I'm doing a check whether the name or a part of the name matches the search term. If there are results, I put the filename and the filepath in the array.
protected function search()
{
$keyword = $this->strKeyword;
$foundResults = array();
$dir_iterator = new RecursiveDirectoryIterator(TL_ROOT."/tl_files/");
$iterator = new RecursiveIteratorIterator($dir_iterator,
RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $splFile) {
if ($splFile->getBaseName() == $keyword) {
array_push($foundResults, $splFile->getBaseName(), $splFile->getPathName());
}
elseif(stripos($splFile->getBaseName(), $keyword) >= 3){
array_push($foundResults, $splFile->getBaseName(), $splFile->getPathName());
}
}
return $foundResults;
}
When I run the code it gives back the following:
[0] => FileName Output 1
[1] => FilePath Output 1
[2] => FileName Output 2
[3] => FilePath Output 2
As you can see , he set a new key for File name and File Path
But what I want is this:
[0] => Example
(
[fileName] => logo.png
[pathName] => /tes/blalabaa/ddddd/logo.png
)
I hope it's a bit clear, and someone can help me.
Greetz
I suppose you need something like this:
$foundResults[] = array(
'fileName' => $splFile->getBaseName(),
'pathName' => $splFile->getPathName());
Instead of the values you can push an array containing the key-value-pairs:
array_push($foundResults,
array(
'fileName' => $splFile->getBaseName(),
'filePath' => $splFile->getPathName()
)
);
Related
I am struggling with what would appear to be a pretty straight forward task. I have looked at and tried all kinds of functions and suggestion on SO hoping that maybe there is something simple and functional out there. Nothing I tried gives me the logic to do the restructuring.
I have a long complex array. However very much simplified the logic problem I am trying to solve generically is as follows:
$cost_type = Array
(
0 => "ISP2",
1 => "ISP3",
2 => "ISP4"
);
$supplier_name = Array
(
0 => "NAME-A",
1 => "NAME-B",
2 => "NAME-C"
);
$propertyid = Array
(
0 => "property1",
1 => "property2",
2 => "property2"
);
and I need to convert it to the following set of arrays (noting the concatenation of the two arrays with a common property id.....
$property1
(
array['charges']
[0] =>IPS2
array ['names']
[0] =>NAME-A
)
$property2
(
array['charges']
[0] ->IPS3
[1] =>IPS4
array['names']
[0] =>NAME-B
[1] =>NAME-c
)
I have tried everything over the course of the last few hours and a simple solution totally evades me.
If you can join the three arrays as you say in comments above this code will generate the look you want.
I loop through the array with property and keep key as the key to find names and charges in the other subarrays.
$cost_type = Array
(
0 => "ISP2",
1 => "ISP3",
2 => "ISP4"
);
$supplier_name =Array
(
0 => "NAME-A",
1 => "NAME-B",
2 => "NAME-C"
);
$propertyid = Array
(
0 => "property1",
1 => "property2",
2 => "property2"
);
$arr[] = $cost_type;
$arr[] = $supplier_name;
$arr[] = $propertyid;
$result = array();
Foreach($arr[2] as $key => $prop){
$result[$prop]["charges"][] =$arr[0][$key];
$result[$prop]["names"][] = $arr[1][$key];
}
Var_dump($result);
https://3v4l.org/EilvE
The following code converts the original array in the expected result:
$res = array();
foreach($arr[2] as $k => $foo){ // foreach property
if(!isset($res[$foo])){ // add property if not yet in list
$res[$foo] = array(
'charges' => array($arr[0][$k]),
'names' => array($arr[1][$k])
);
}else{ // add new value to already existing property
$res[$foo]['charges'][] = $arr[0][$k];
$res[$foo]['names'][] = $arr[1][$k];
}
}
Check it out here: https://eval.in/904473
Of course, it assumes a bunch on things about the data, but it should work for any number of items.
And if you need the property in another variable, just access it with $res['name of it].
Run this code you will get smiler result as you want :
$twodimantion=array();
$properties=array('property1','property2','property3');
$charges=array('ISP2','ISP3','ISP4');
$names=array('NAME-A','NAME-B','NAME-C');
foreach ($properties as $key => $property) {
$twodimantion['charge'][$key]=$charges[$key];
$twodimantion['names'][$key]=$names[$key];
$twoarray[$property]=$twodimantion;
}
echo '<pre>';
print_r($twoarray);
echo '</pre>';
I can't say I completely follow what you are trying to do, but I think this may be part of the way there for you.
When trying to restructure data in PHP, it's often helpful to create a empty array (or other data structure) to store the new data in first. Then you find a way to loop over your initial data structure that allows you to insert items into your reformatted structure in the right sequence.
<?php
$properties = []; // Array to hold final result
// Loop over your initial inputs
foreach ($groupsOfValues as $groupName => $groupValues) {
$temp = []; // Array to hold each groupings reformatted data
// Loop over the items in one of the inputs
for ($i=0; $i<count($group) && $i<count($properties)+1; $i++) {
if (!is_array($temp[$groupName])) {
$temp[$groupName] = [];
}
$temp[$groupName][] = $group[$i];
}
$properties[] = $temp;
}
I am trying to return pull a value based on an attribute from an array, and it seems straight forward enough but I can't seem to nail down the correct way to accomplish this.
Here is the array I am trying to pull from:
[1] => InfoOptions Object
(
[description] => INFO
[optSequence] => 2
[eqpObject] => CUSTOMER NTWK ENG
[attribute] =>
[eqpValue] =>
[dlrSequence] => 10
)
[2] => InfoOptions Object
(
[description] =>
[optSequence] => 3
[eqpObject] => CUSTOMER TEST
[attribute] => CUSTOMER
[eqpValue] => Jon Doe
[dlrSequence] => 10
)
Here is what I have so far:
if (is_array($provisionCVResult->path->infoOptions-_InfoOptions)) {
foreach ($provisionCVResult->path->infoOptions ->InfoOptions as $cv_obj) {
$CVA = array();
$result = null;
foreach ($CV_obj as $value) {
if($value['attribute'] == 'CUSTOMER') {
$CVA["eqpValue"] = $cv_obj->eqpValue;
break;
}
}
$this->cvArrayDataList[] = $CVA;
}
}
Where am I going wrong?
If $provisionCVResult->path->InfoOptions is an array, it does not make sense to write $provisionCVResult->path->InfoOptions ->InfoOptions in the foreach
EDIT: I red in the comments that the array is $provisionCVResult->path->InfoOptions->InfoOptions
PHP is case sensitive so $cv_obj and $CV_obj are two different variables
The second foreach is not needed
So, assuming $provisionCVResult->path->InfoOptions->InfoOptions is returning an array of InfoOptions Object, I think you should do something like this:
if (is_array($provisionCVResult->path->InfoOptions->InfoOptions))
{
$result = null;
foreach($provisionCVResult->path->InfoOptions->InfoOptions as $cv_obj)
{
if($cv_obj->attribute == 'CUSTOMER')
{
$this->cvArrayDataList[] = array("eqpValue" => $cv_obj->eqpValue);
}
}
}
Having a quick look, try changing
$value['attribute'] == 'CUSTOMER'
To
$value->attribute == 'CUSTOMER'
As the element is an "InfoOptions object" and not an array.
Note I would also recommend using strict comparison, e.g '===' instead of '=='.
can someone tell me what is this code doing, As im new to Yii, learning about it.. im not able to understand few things.. Here is the code..
$allmsg = LogMsg::model()->findAll($criteria); //
$dataArr = array();
if (isset($allMsg) && sizeof($allMsg) != 0):
foreach ($allMsg as $msg) {
$dataArr[$msg->date][] = array( // array?
'category' => $msg->category, // what is that 'category' a variable or something else? and $msg->category, is what?
'time' => $msg->time,
'date' => $msg->date,
'user' => $msg->name
);
} endif;
$this->render('index', array(
'data' => $dataArr ) //what is that 'data'?
);
My question is, what is this line of code doing exactly in foreach loop
$dataArr[$msg->date][] = array(
'category' => $msg->category,
and here is second code... which has something like that..
$allCat = Categories::model()->findAll($criteria);
$catArr=array();
if(isset($allCat) && sizeof($allCat)!=0):
foreach ($allCat as $catModel) {
$catArr[$catModel->id] =$catModel;
}
endif;
return $catArr;
so what is this line doing in this code in foreach loop, what is different between these two lines in first and second code..
$catArr[$catModel->id] =$catModel;
last thing.. what is it
public static function getID($category)
{
$arr = array(
'ast'=>1, // what are these things? from where are they coming? db?
'fp'=>5, //
'per'=>3,
'ts'=>6,
'lg'=>3
);
return isset($arr[$category])?$arr[$category]:null; //Ternary - Condensed if/else statement
}
So as per your first question.
$dataArr[$msg->date][] = array(
'category' => $msg->category,
$allMsg is the active record object which u get through the db query. This object is traversed in a loop and each row is "$msg".
Hence you can access the attributes of the model through the $msg->category. 'category' here is the attribute of the model.
this is creating multidimensional array.
Your first question
$dataArr[$msg->date][] = array(
'category' => $msg->category,
will generate output like
[2016-03-04] => Array
(
[0] => Array
(
[category] => abc
)
)
And your second question
$catArr[$catModel->id] =$catModel;
will genrate output like
array(
[0] =>1,
[1] => 2,
[2] => 3,
)
Not tested.
I think, your question is not about Yii. You should read about arrays of PHP first. In the code multidimensional array have been used. It means that the array can contain another array as value.
I have data contained in an array which is like so,
$file['info']['files'] = array(
[0] => array(
'length' => (int),
'path' => array (
[0] => 'file.txt',
),
),
[1] => array(
'length' => (int),
'path' => array (
[0] => 'directory one',
[1] => 'file2.txt',
),
),
[2] => array(
'length' => (int),
'path' => array (
[0] => 'directory one',
[1] => 'directory two',
[2] => 'file3.txt',
),
),
);
The $file['info']['files'] array can contain any number of elements. The path array contained in each $file['info']['files'] array is where I am having trouble.
It contains information about a file structure. If just 1 element exists then it is a file. If more than one element exists then each element starting from the top is a parent folder of the next element and the last element is the file in the last folder. Taking the example above would be a file structure of
FILE file1.txt
FOLDER directory one
FILE file2.txt
FOLDER directory two
FILE {file3.txt}
I would like to extract this data into my own array structure which is to be as follows,
$sortedFiles = array(
'file1.txt' => (int),
'directory one' => array(
'file2.txt' => (int),
'directory two' => array(
'file3.txt' => (int),
),
),
);
I have this code so far,
foreach($file['info']['files'] as $file) {
// LENGTH AND PATH ARE SET
if(isset($file['length'], $file['path'])) {
// GET COUNT OF FILE PATH ARRAY
$count = count($file['path']);
// SINGLE FILE
if($count == 1) {
$sortedFiles[$file['path'][0]] = $file['length'];
// FILES IN DIRECTORY
} else {
// BUILD ARRAY STRUCTURE FOR DIRECTORIES
}
}
}
I am having trouble when it comes to adding directories to the array. I could do it manually and only go so many directories down each time checking if the array for the directory exists and if not create it, and if it does exist then add to it. I tried this with the code below but it only goes one directory deep (the code went where it says // BUILD ARRAY STRUCTURE above).
// FOLDER NOT SET
if(!isset($files[$file['path'][0]])) {
$sortedFiles[$file['path'][0]] = array($file['path'][1] => $file['length'],);
// FOLDER SET
} else {
$sortedFiles[$file['path'][0]][$file['path'][1]] = $file['length'];
}
How can I dynamically create arrays for each directory that exists and add the information that is needed bearing in mind that the directory structure could be any amount of levels deep?
Thanks for taking the time to read my rather long question and I appreciate any help that anyone gives to me.
You will need to call your function recursively, as in the example below:
function get_contents_dir( $dir )
{
$names = array();
if ( is_dir($dir) && is_readable($dir) )
{
foreach ( scandir($dir) as $file )
{
if ( is_dir($dir."/".$file) && is_readable($dir."/".$file) )
{
$names[] = get_contents_dir($dir."/".$file);
}
if ( is_file($dir."/".$file) && is_readable($dir."/".$file) )
{
$names[] = $dir."/".$file;
}
}
}
return $names;
}
This function first opens the set $dir folder and scans the list of files, adding each found file to the array which is, after scanning the folder, returned as the return value of the function.
The twist comes in when an entry of the scandir() result (list of files and folders in the folder) is actually a folder. If that happens, the function is called from it's internals, recursively (see the line $names[] = get_contents_dir($dir."/".$file); calling the function from within the function) and the subfolder will be indexed too. Rinse and repeat, until all subfolders are indexed.
If you call the function and let it execute, an array will be returned. Each key of the array will be an entry. If it was a file, the value linked to the key is the name of the file, if it was a folder, the value will be another array nested into the previous one.
Here is an example dump taken of the returned array:
array (
0 => './libmysqlclient.so.16.0.0',
1 => './libmysqlclient_r.so.16.0.0',
2 =>
array (
0 => './libs/libboost_thread-mt.a',
1 => './libs/libboost_thread-mt.so.1.38.0',
2 => './libs/libmysql.dll',
3 => './libs/libmysqlclient16_5.1.41-3ubuntu12_i386.deb',
),
3 =>
array (
0 => './radio_sneaker/cl_auto.lua',
1 => './radio_sneaker/sh_auto.lua',
2 => './radio_sneaker/sh_coms.lua',
3 => './radio_sneaker/sh_info.lua',
4 => './radio_sneaker/sv_auto.lua',
5 => './radio_sneaker/sv_hooks.lua',
),
4 => './sv_auto.lua',
)
Compare this output against the tree command ran on the same folder:
| libmysqlclient.so.16.0.0
| libmysqlclient_r.so.16.0.0
| sv_auto.lua
|
+---libs
| libboost_thread-mt.a
| libboost_thread-mt.so.1.38.0
| libmysql.dll
| libmysqlclient16_5.1.41-3ubuntu12_i386.deb
|
\---radio_sneaker
cl_auto.lua
sh_auto.lua
sh_coms.lua
sh_info.lua
sv_auto.lua
sv_hooks.lua
Why don't you use a join function in php to merge the path to check whether it then exists? If it doesn't then go level by level checking if the folder exists and if it doesn't then create in and move further. My point is that creating such a dynamic structure is, first of all, difficult and easy to mess up. Why not to go the easy way?
Imagine that you have an array representing the directory stucture which is initially empty and will be filled in piece by piece. You need to keep track of a "current" item in this array and iterate over the directory names. At each iteration you would create a sub-array under the current item if it does not already exist and then set the current to be this sub-array.
This can be done either with recursion or with iteration, and since it's PHP the "current" marker would need to be a reference.
With this overview in mind, have a look at this question and the answers there. The input there is in the form of a string, but that's just an implode away from your current situation.
I'll let you wrestle this into your code, but heres the important lessons.
turn the flat array into a nested structure
$a = array(
'dir1', 'dir2', 'file.txt'
);
$structure = array(array_pop($a));
foreach (array_reverse($a) as $dir) {
$structure = array($dir => $structure);
}
print_r($structure);
merge one structure into another
$result = array_merge_recursive($result, $structure);
Just iterate over all structures for the merging.
So I have a function that merges two arrays replacing "variables" that are in the $template array with values from the $marketArray. It's nice tight bit of code from some kind contributor's here. Now due to a new requirement I need to switch things a bit.
First I need to make it an array of arrays that essentially groups the stuff by market instead of one giant list in a single large array. Secondly I need the keys in the new arrays to be of the format market-counter
e.g. gb/en-1, gb/en-2 etc etc (this is so a JQuery gets an id it can use to determine where the results go later.
So I have entered a couple of new entries (marked //NEW) that would get the value for the market and started a counter. It's twisting my brain around the next step that hurts!
$marketArray is a multidimensional associative array of the markets like this (but a lot more markets!)
$markets = array(
array(market => 'se/sv', storeid => 'storeId=66', langid => 'langId=-14', storenumber => '109', prodid => '741586', artid => '22112334'),
array(market => 'at/de', storeid => 'storeId=82', langid => 'langId=-11', storenumber => '234', prodid => '374637', artid => '45678214')
);
$template is a bunch of url templates that need to be manipulated on a market by market basis (again shortened)
$template = array (
'/$market',
'/$market/catalog/',
'/$marketproducts/$artid',
'StockSearchForm?&productId=$prodid'
);
Here is the function
function urlBuilder($marketArray,$template) {
$urlstohit=array();
foreach ($marketArray as $m) {
$market = $m['market']; //NEW
$counter = 1; //NEW
foreach ($template as $t) {
$tt=$t;
foreach ($m as $k=>$v)
$tt=str_replace('$'.$k, $v, $tt);
$urlstohit[]=$tt;
}
}
return ($urlstohit);
}
so what I am trying to achieve is instead of one giant array like
$urlstohit (
[0] => '/se/sv/catalog/categories/',
[1] => '/se/sv/catalog/news/',
[2] => '/se/sv/catalog/categories/departments/',
[3] => '/se/sv/search/?query=giant'
[4] => '/at/de/catalog/categories/',
[5] => '/at/de/catalog/news/',
[6] => '/at/de/catalog/categories/departments/',
[7] => '/at/de/search/?query=giant'
)
a md-array grouped by market with the market-counter as keys
$urlstohit (
['se/sv'] => array(
['se/sv-1'] => '/se/sv/catalog/categories/',
['se/sv-2'] => '/se/sv/catalog/news/',
['se/sv-3'] => '/se/sv/catalog/categories/departments/',
['se/sv-4'] => '/se/sv/search/?query=giant'
),
['at/de'] => array(
['at/de-1'] => '/at/de/catalog/categories/',
['at/de-2'] => '/at/de/catalog/news/',
['at/de-3'] => '/at/de/catalog/categories/departments/',
['at/de-4'] => '/at/de/search/?query=giant'
)
)
Try this
function urlBuilder($marketArray,$template) {
$urlstohit=array();
foreach ($marketArray as $m) {
$market = $m['market'];
$counter = 1;
$urlstohit[$market] = array(); / ADDED
foreach ($template as $t) {
$tt=$t;
foreach ($m as $k=>$v)
$tt=str_replace('$'.$k, $v, $tt);
$urlstohit[$market][$market.'-'.$counter]=$tt; // EDITED
$counter++; // ADDED
}
}
} // ADDED
return ($urlstohit);
}
I've marked the lines I've added and edited (I think you were also missing a curly brace).