I have an array of arrays that contain array key with the value, here the example :
$text = [
[
'Hotel' => 'N',
'Jayakarta' => 'NE',
'Jaya' => 'NE',
'sangat' => 'ADV',
'nyaman' => 'ADJ',
'ditempati' => 'V.'
]
,
[
'Andi' => 'NOB',
'menginap' => 'V',
'di' => 'PREP',
'Hotel' => 'N',
'Neo' => 'NE',
'Malioboro => 'NE',
'selama' => 'N',
'satu' => 'NUM',
'minggu' => 'N.'
]
];
And I have array prefix that contain :
$prefix = [ [0] => Hotel [1] => Hostel [2] => Losmen [3] => Motel [4] => Penginapan [5] => Pesanggrahan [6] => Pondok [7] => Wisma ]
If $prefix elements are in $text array then I will check next array value of text. If array value is N or NE then I will make an output from prefix text until the end of array that contain value N or NE.
Here's what I am doing for the moment:
foreach($text as $index => $tok){
foreach ($tok as $tokkey => $tokvalue) {
if(in_array($tokkey, $prefix)){
echo $tokkey;
$next = next($tok);
if($tokvalue == "N" or $tokvalue == "NE"){
echo key($tok);
}
}
}
}
The output I got :
Hotel Jayakarta, Hotel menginap
The expected output should be:
- Hotel Jayakarta Jaya
- Hotel Neo Malioboro selama
Any help is much appreciated, Thank you.
Below are the steps I followed to get the desired out put.
1) If tokkey present in prefix array, call a function.
2) Create a new array starting from the element which matches with prefix array.
3) Loop the new array and check for next value to be either 'N' or 'NE'
4) Display those keys from array.
foreach($text as $index => $tok){
foreach ($tok as $tokkey => $tokvalue) {
if(in_array($tokkey, $prefix)){
getKeys($tokkey,$tok);
echo "<br/>";
}
}
}
function getKeys($tokkey,$tok){
$flag = 0;
echo $tokkey.' ';
foreach($tok as $k=>$v){
if($k==$tokkey){
$flag = 1;
}
if($flag){
$new_array[$k]=$v;
}
}
foreach($new_array as $k=>$v){
$ff = next($new_array);
if(($ff == 'NE' || $ff == 'N')){
echo key($new_array).' ';
}
}
}
Out Put:
Hotel Jayakarta Jaya Hotel Neo Malioboro selama
http://sandbox.onlinephpfunctions.com/code/2777d3ab3d34c941c23886d42e537cde7fff2351
From what I understand from your text, you need to replace your if() that only runs once, for a while() that runs while the next() string is NE or N.
foreach($text as $index => $tok){
foreach ($tok as $tokkey => $tokvalue) {
if(in_array($tokkey, $prefix)){
echo $tokkey;
next($tok);
while($tokvalue == "N" || $tokvalue == "NE")
{ echo key($tok);
next($tok);
$tokvalue = current($tok);
}
}
}
echo "\n";
}
}
Related
I am using Spout Excel reader to read Excel files from php code and saving into a multidimensional array in PHP variable,Array looks like this
$array = [
[
'id[0]' => 'BX-78',
'Name[0]' => 'XXX',
'Address[0]' => 'YUUSATD'
],
[
'id[1]' => 'BX-79',
'Name[1]' => 'YYY',
'Address[1]' => 'DHJSHDJGY'
],
[
'id[2]' => 'BX-80',
'Name[2]' => 'ZZZ',
'Address[2]' => 'DDSDSDA'
]
[
'id[3]' => 'BX-78',
'Name[3]' => 'AAA',
'Address[3]' => 'FSDSDS'
][
'id[4]' => 'BX-81',
'Name[4]' => 'XXX',
'Address[4]' => 'DSDSDSD'
]];
Now i want to show duplicate data from above array using two keys ['id'] and ['name'] if id repeats show as duplicate data,
If name repeats show that row as duplicate data if both are duplicate show as again duplicate row
Otherwise it is unique row.
I have tried using multidimensional array sorting but it is using only one key to match data in rows.
foreach ($arrExcelData as $v) {
if (isset($arrExcelData[$v[0]])) {
// found duplicate
continue;
}
// remember unique item
$arrExcelData3[$v[0]] = $v;
}
// if you need a zero-based array, otheriwse work with $_data
$arrExcelData2 = array_values($arrExcelData3);
Edited : Expected Output Result :
Matching Rows:
Id Name Address
-------------------------
BX-78 XXX YUUSATD
BX-78 AAA DDSDSDA
BX-81 XXX DSDSDSD`
If you want to list the duplicate values, I think the address of the second match should be FSDSDS as there is not item with name AAA and value DDSDSDA:
BX-78 AAA FSDSDS
If that is the case, what you could do is to first use a double foreach to mark the arrays that contain a duplicate id or name by for example adding a property named id and name except when the array is itself in the second loop.
After this loop, you can tell which arrays are the duplicate ones. Instead of using a corresponding index 0 as in id[0], I have used reset and next so it is not tied to these indexes.
To get the filtered result you could use array_reduce to check for the array keys and unset them.
For example:
foreach ($array as $index => $a) {
foreach ($array as $v) {
if ($v === $a) continue;
if (reset($v) === reset($a)) $array[$index]["id"] = "duplicate";
if (next($v) === next($a)) $array[$index]["name"] = "duplicate";
}
}
$array = array_reduce($array, function($carry, $item) {
if (array_key_exists("id", $item) || array_key_exists("name", $item)) {
unset($item["id"], $item["name"]);
$carry[] = $item;
}
return $carry;
}, []);
print_r($array);
Result
Array
(
[0] => Array
(
[id[0]] => BX-78
[Name[0]] => XXX
[Address[0]] => YUUSATD
)
[1] => Array
(
[id[3]] => BX-78
[Name[3]] => AAA
[Address[3]] => FSDSDS
)
[2] => Array
(
[id[4]] => BX-81
[Name[4]] => XXX
[Address[4]] => DSDSDSD
)
)
See a php demo
I've this very pragmatic approach:
$spout_output = [
[
'id[0]' => 'BX-78',
'Name[0]' => 'XXX',
'Address[0]' => 'YUUSATD'
],
[
'id[1]' => 'BX-79',
'Name[1]' => 'YYY',
'Address[1]' => 'DHJSHDJGY'
],
[
'id[2]' => 'BX-80',
'Name[2]' => 'ZZZ',
'Address[2]' => 'DDSDSDA'
],
[
'id[3]' => 'BX-78',
'Name[3]' => 'AAA',
'Address[3]' => 'FSDSDS'
],
[
'id[4]' => 'BX-81',
'Name[4]' => 'XXX',
'Address[4]' => 'DSDSDSD'
]];
// store id to row, and name to row mappings.
// id and name will be keys, value will be an array of indexes of the array $spout_output
$id_to_rows = array();
$name_to_rows = array();
$duplicate_ids = array();
$duplicate_names = array();
foreach($spout_output as $row => $data)
{
$key_id = 'id['.$row.']';
$key_name = 'Name['.$row.']';
if(!isset($data[$key_id]))
continue;
$value_id = $data[$key_id];
$value_name = $data[$key_name];
if(!isset($id_to_rows[$value_id]))
{
$id_to_rows[$value_id] = array();
}
else
{
if(!isset($duplicate_ids[$value_id]))
{
$duplicate_ids[$value_id] = $id_to_rows[$value_id];
}
$duplicate_ids[$value_id][] = $row;
}
if(!isset($name_to_rows[$value_name]))
{
$name_to_rows[$value_name] = array();
}
else
{
if(!isset($duplicate_names[$value_name]))
{
$duplicate_names[$value_name] = $name_to_rows[$value_name];
}
$duplicate_names[$value_name][] = $row;
}
$id_to_rows[$value_id][] = $row;
$name_to_rows[$value_name][] = $row;
}
echo 'Duplicates:';
echo '<br>';
$shown_rows = array();
foreach($duplicate_ids as $id => $rows)
{
foreach($rows as $nr)
{
echo $id . '|' . $spout_output[$nr]['Name['.$nr.']'] . '|' . $spout_output[$nr]['Address['.$nr.']'];
echo '<br>';
$shown_rows[] = $nr;
}
}
foreach($duplicate_names as $name => $rows)
{
foreach($rows as $nr)
{
// if already shown above, skip this row
if(in_array($nr, $shown_rows))
continue;
echo $spout_output[$nr]['id['.$nr.']'] . '|' . $spout_output[$nr]['Name['.$nr.']'] . '|' . $spout_output[$nr]['Address['.$nr.']'];
echo '<br>';
$shown_rows[] = $nr;
}
}
Outputs:
Duplicates:
BX-78|XXX|YUUSATD
BX-78|AAA|FSDSDS
BX-81|XXX|DSDSDSD
I think your 'wanted output' contains an error in the address?
Anyway, with my code above I think you'll have enough mapped data to produce the output you want.
You could do something like this:
$dupes = [];
$current = [];
foreach ($array as $index => $entry) {
$idKey = "id[$index]";
$nameKey = "Name[$index]";
if (array_key_exists($entry[$idKey], $current)) {
$dupes[] = [$entry, $current[$entry[$idKey]]];
}
elseif (array_key_exists($entry[$nameKey], $current)) {
$dupes[] = [$entry, $current[$entry[$nameKey]]];
}
else {
$current[$entry[$idKey]] = $current[$entry[$nameKey]] = $entry;
}
}
print_r($dupes);
Which results in an array containing each set of duplicates (array of arrays):
Array
(
[0] => Array
(
[0] => Array
(
[id[3]] => BX-78
[Name[3]] => AAA
[Address[3]] => FSDSDS
)
[1] => Array
(
[id[0]] => BX-78
[Name[0]] => XXX
[Address[0]] => YUUSATD
)
)
[1] => Array
(
[0] => Array
(
[id[4]] => BX-81
[Name[4]] => XXX
[Address[4]] => DSDSDSD
)
[1] => Array
(
[id[0]] => BX-78
[Name[0]] => XXX
[Address[0]] => YUUSATD
)
)
)
Demo here: https://3v4l.org/JAtNU
In case someone of you are searching unique values by key.
function unique_multidim_array($array, $key) {
$temp_array = array();
$i = 0;
$key_array = array();
foreach($array as $val) {
if (!in_array($val[$key], $key_array)) {
$key_array[$i] = $val[$key];
$temp_array[$i] = $val;
}
$i++;
}
return $temp_array;
}
This function just takes multidimensional array and key value of field you need.
Then takes value of given array one by one (smaller arrays).
Then traverses given array and looking if taken key-value pair matches with given key.
After that if taken key-value pair matches with given key function just inserts smaller array in temporary array (array with unique values).
Don't forget to increment indexes of arrays ($i).
Then return array you got (with unique values) after function ends work.
I have an array of arrays that contain array key with the value, here the example :
Array (
[0] => Array ( [Hotel] => N [Jayakarta] => NE [Jaya] => NE [sangat] => ADV [nyaman] => ADJ [ditempati] => V. )
[1] => Array ( [Andi] => NOB [Hotel] => N [menginap] => V [disana] => N [selama] => N [satu] => NUM [minggu] => N. )
)
I want to make an output if I found a key of "Hotel" then I will print next key from "Hotel". For example :
Hotel Jayakarta Jaya
Hotel menginap disana
Here's what I am doing for the moment:
foreach($token2 as $index => $tok){
foreach ($tok as $tokkey => $tokvalue) {
if ($tokkey == "Hotel" and $tokvalue == "N"){
echo $tokkey . " " ;
while($cek == true && $x <= 2){
$next = next($tok);
echo key($tok). " " ;
$x++;
}
echo ", ";
$x = 1;
}
}
}
And the output :
Hotel Jayakarta jaya sangat , Hotel Hotel menginap
The Expected Output should be as below:
Hotel Jayakarta jaya sangat , Hotel menginap disana selama
Any help is much appreciated, Thank you.
Do something like following:
$i = 3;
foreach($token2 as $index => $tok){
foreach ($tok as $tokkey => $tokvalue) {
if ($tokkey == "Hotel" && $tokvalue == "N"){
echo $tokkey . " " ;
$i = 1;
}
else if($i < 3){
echo $tokkey . " ";
$i++;
}
}
echo ", ";
}
maybe you could try this ?
$arrayOfHotels = array(0 => array('Hotel' => 'N' , 'Jakarta' => 'NE', 'Jaya' => 'NE', 'sangat' => 'ADV', 'nyaman' => 'ADJ', 'ditempati' => 'V.'),1 => array('Andi' => 'NOB', 'Hotel' => 'N', 'menginap' => 'V', 'disana' => 'N', 'selama' => 'N', 'satu' => 'NUM', 'minggu' => 'N.'));
echo '<pre>';
print_r(findHotel($arrayOfHotels));
echo '</pre>';
function findHotel($hotels)
{
$isHotelFind = false;
$isFirstThrough = true;
foreach($hotels as $row => $value)
{
foreach ($value as $row2 => $value2)
{
if($row2 == "Hotel" && $value = 'N' && !$isHotelFind)
{
if($isFirstThrough)
{
echo $row2 . " ";
}
else
{
echo ", " . $row2 . " ";
}
$isHotelFind = true;
$isFirstThrough = false;
}
if($isHotelFind && $row2 != "Hotel")
{
echo $row2 . " ";
}
}
$isHotelFind = false;
}
}
You can use array_search to find your key and remove leading elements before it.
$array = [
[
"Hotel" => 'N',
"Jayakarta" => 'NE',
'Jaya' => 'NE',
'sangat' => 'ADV',
'nyaman' => 'ADJ',
'ditempati' => 'V.'
]
,
[
"Andi" => 'NOB',
"Hotel" => 'N',
'menginap' => 'V',
'disana' => 'N',
'selama' => 'N',
'satu' => 'NUM',
'minggu' => 'N.'
]
];
foreach ($array as $data) {
// Find index to start
$index = array_search("Hotel", array_keys($data));
// Remove other keys
$new_array_starting_hotel = array_splice($data, $index, count($data));
// merge results
$merged[] = implode(' ', array_keys($new_array_starting_hotel));
}
print_r($merged);
And output will be like:
Array
(
[0] => Hotel Jayakarta Jaya sangat nyaman ditempati
[1] => Hotel menginap disana selama satu minggu
)
You can merge or implode all however you like.
I have two arrays I want to compare these two arrays and find the match. If 807 and 200 appears in same keys like 131 then create third array
array(131=>(807,200));
array1:-
Array([0] => 807,[1] => 200)
array2 :-
$mat= Array([0] => Array([131] => 807),[1] => Array([132] => 807),[2] => Array([125] => 200),[3] => Array([131] => 200))
My code:
<?php
$filtered = array();
array_walk_recursive($matchingskusarr, function($val, $key) use(&$filtered) {
if ($key === 131) {
echo "The key $key has the value $val<br>";
$filtered[$val] = $key;
}
});
echo "<pre>";
print_r($filtered);
echo "</pre>";
?>
You can use array_column like this:
$filtered = array_column($mat, 131);
//Output: Array ( [0] => 807 [1] => 200 )
Update 1:
$matchingskusarr = Array( 0 => Array(131 => 807), 1 => Array(132 => 807),2 => Array(125 => 200),3 => Array(131 => 200)) ;
$skus = array(0=>807, 1=>200);
function yourMatch($skus, $matchingskusarr) {
$continue = [];
foreach ($matchingskusarr as $array) {
//Get the first key !!!
foreach ($array as $key => $value);
//Column already tested just continue
if(isset($continue[$key])) {
continue;
}
//New column we need to check if it matches our $skus
$column = array_column($matchingskusarr, $key);
if($column == $skus) {
return [$key => $column ];
}
$continue[$key] = true;
}
return null;
}
print_r(yourMatch($skus, $matchingskusarr));
Demo: https://3v4l.org/Cr2L4
I have three variables
$region ='APJ';
$sub_region = 'India';
$country = 'India'
and i have multiple arrays like
Array
(
[0] => Array
(
[region] => APJ
[subregion] => India
[country] =>
)
[1] => Array
(
[region] => APJ
[subregion] =>china
[country] =>
)
[2] => Array
(
[region] => WW
[subregion] =>france
[country] => France
)
[3] => Array
(
[region] => EMEA
[subregion] =>mema
[country] => France
)
)
I need to find the perfect match array for using these three variables.
In the above example we have 4 arrays with different values.
First array matching region and sub region level also.
Second array only region level is matching.
All other are not matching even one value also.
So i choose the first array as result.
So using php how i find the perfect matching array in this kind of scenario?
Concept: "Ranking"
Create a comparison array with the same structure as the definiton arrays
Loop through all definitions and …
Count matches (rank) for each definition (loop through comparison array).
Store the mathing level (rank) in the definition array itself (additional key: _level).
Keep the index of the highest ranked definition array.
Result: The index of the definition array with the highest rank ($highestlevel).(= The first definition with the highest ranking)
Code
<?php
$defs = array ( // Definitions
array(
'region' => 'APJ', // to be compared
'country' => '', // to be compared
'typeofrec' => 1,
'TotalAllocations' => 0,
'TotalTransfersOut' => 0,
'subregion' => 'India', // to be compared
'TotalTransfersIn' => 0,
'StartOfAllocation' => 0,
'ApprovedActivities' => 10,
'AvailableBalance' => -10,
'Exposure' => 0,
),
array(
'region' => 'APJ',
'subregion' => 'china ',
'country' => '',
),
array(
'region' => 'WW',
'subregion' => 'france',
'country' => 'France',
),
array(
'region' => 'EMEA',
'subregion' => 'mema',
'country' => 'France',
),
);
// Comparison array
// Instead of ...
// $region ='APJ';
// $sub_region = 'India';
// $country = 'India'
$testarray = array( // Comparison array
'region' => 'APJ',
'subregion' => 'India',
'country' => 'India',
);
// --------------------------------------------------------------------------
$highestlevel = 0; // Index of highest ranked definition
foreach ($defs as $ix => $def) { // Loop through all definitions
$defs[$ix]['_level'] = 0; // Add new entry to array
foreach($testarray as $key => $value) { // Loop throug comparison values
// Increment ranking level if matched
if (trim($def[$key]) == trim($value)) $defs[$ix]['_level']++;
// Variant "case ignored":
// if (strtolower(trim($def[$key])) == strtolower(trim($value))) $defs[$ix]['_level']++;
}
// Keep index of highest ranked
if (!isset($defs[$highestlevel]['_level']) || $defs[$highestlevel]['_level'] < $defs[$ix]['_level']) $highestlevel = $ix;
}
// --------------------------------------------------------------------------
// Display the result
echo '<h3>Result</h3><pre>'; var_dump($defs[$highestlevel]); echo '</pre>';
Main advantages:
Flexibility:The code only assumes array structures. Neither key names nor element types nor fixed array lengths are assumed. So it Works with different values and array lengths.
Compactness.
Result
array(12) {
["region"]=> string(3) "APJ"
["country"]=> string(0) ""
["typeofrec"]=> int(1)
["TotalAllocations"]=> int(0)
["TotalTransfersOut"]=> int(0)
["subregion"]=> string(5) "India"
["TotalTransfersIn"]=> int(0)
["StartOfAllocation"]=> int(0)
["ApprovedActivities"]=> int(10)
["AvailableBalance"]=> int(-10)
["Exposure"]=> int(0)
["_level"]=> int(2)
}
Please try this
$region ='APJ';
$sub_region = 'India';
$country = 'India'
$ret ="";
foreach($yourarr as $key=> $subArr){
/* If region,subregion & country values matches given data return mached array value */
if($subArr['region'] == $region && $subArr['subregion'] == $sub_region && $subArr['country'] == $country){
$matArr = $arr[$key];
break;
}
/* Else If any of the 2 matches with given data return the specific array value */
else if(
($subArr['region'] == $region && $subArr['subregion']) ||
($subArr['subregion'] == $sub_region && $subArr['country'] == $country ) ||
($subArr['region'] == $region && $subArr['country'] == $country )
){
$matArr = $arr[$key];
break;
}
/* Else any of the value matches return the specific array value*/
else if($subArr['region'] == $region || $subArr['subregion'] == $sub_region || $subArr['country'] == $country){
$matArr = $arr[$key];
break;
}
}
echo "Matching Array Is:";
print_r($matArr);
for($i=0;$i<count($arr);$i++)
{
if(($arr[$i]['region']==$region) && ($arr[$i]['subregion']==$sub_region) && ($arr[$i]['country']==$country) )
{
echo "3"."index".$i;
}
elseif( (($arr[$i]['region']==$region) && ($arr[$i]['subregion']==$sub_region)) || ( ($arr[$i]['subregion']==$sub_region) && ($arr[$i]['country']==$country) ) || ( ($arr[$i]['region']==$region) && ($arr[$i]['country']==$country) ) )
{
echo "2"."index".$i;
}
elseif(($arr[$i]['region']==$region) || ($arr[$i]['subregion']==$sub_region) || ($arr[$i]['country']==$country))
{
echo "1"."index".$i;
}
else
{
echo "not found";
}
}
$arr is your array.
in above code it first search for perfect match means all case are matche
in second case it match for two
in third case it match for atleast one
3 is the top priority and get the index value
I'm fairly sure I'm missing something blindingly obvious here but here it goes.
I am working on updating a search function in an application which was running a loop and doing a very large number of sql queries to get object / table relations to one large query that returns everything. However the only way I could think to return relations was period separated, what I am now wanting to do is take the flat array of keys and values and convert it into an associative array to then be jsonified with json_encode.
For example what I have is this...
array(
"ID"=>10,
"CompanyName"=>"Some Company",
"CompanyStatusID"=>2,
"CompanyStatus.Status"=>"Active",
"addressID"=>134,
"address.postcode"=>"XXX XXXX",
"address.street"=>"Some Street"
);
And what I want to turn it into is this...
array(
"ID"=>10,
"CompanyName"=>"Some Company",
"CompanyStatusID"=>2,
"CompanyStatus"=>array(
"Status"=>"Active"
),
"addressID"=>134,
"address"=>array(
"postcode"=>"XXX XXXX",
"street"=>"Some Street"
)
);
Now I'm sure this should be a fairly simple recursive loop but for the life of me this morning I can't figure it out.
Any help is greatly appreciated.
Regards
Graham.
Your function was part way there mike, though it had the problem that the top level value kept getting reset on each pass of the array so only the last period separated property made it in.
Please see updated version.
function parse_array($src) {
$dst = array();
foreach($src as $key => $val) {
$parts = explode(".", $key);
if(count($parts) > 1) {
$index = &$dst;
$i = 0;
$count = count($parts)-1;
foreach(array_slice($parts,0) as $part) {
if($i == $count) {
$index[$part] = $val;
} else {
if(!isset($index[$part])){
$index[$part] = array();
}
}
$index = &$index[$part];
$i++;
}
} else {
$dst[$parts[0]] = $val;
}
}
return $dst;
}
I am sure there is something more elegant, but quick and dirty:
$arr = array(
"ID"=>10,
"CompanyName"=>"Some Company",
"CompanyStatusID"=>2,
"CompanyStatus.Status"=>"Active",
"addressID"=>134,
"address.postcode"=>"XXX XXXX",
"address.street"=>"Some Street"
);
$narr = array();
foreach($arr as $key=>$val)
{
if (preg_match("~\.~", $key))
{
$parts = split("\.", $key);
$narr [$parts[0]][$parts[1]] = $val;
}
else $narr [$key] = $val;
}
$arr = array(
"ID" => 10,
"CompanyName" => "Some Company",
"CompanyStatusID" => 2,
"CompanyStatus.Status" => "Active",
"addressID" => 134,
"address.postcode" => "XXX XXXX",
"address.street" => "Some Street",
"1.2.3.4.5" => "Some nested value"
);
function parse_array ($src) {
$dst = array();
foreach($src as $key => $val) {
$parts = explode(".", $key);
$dst[$parts[0]] = $val;
if(count($parts) > 1) {
$index = &$dst[$parts[0]];
foreach(array_slice($parts, 1) as $part) {
$index = array($part => $val);
$index = &$index[$part];
}
}
}
return $dst;
}
print_r(parse_array($arr));
Outputs:
Array
(
[ID] => 10
[CompanyName] => Some Company
[CompanyStatusID] => 2
[CompanyStatus] => Array
(
[Status] => Active
)
[addressID] => 134
[address] => Array
(
[street] => Some Street
)
[1] => Array
(
[2] => Array
(
[3] => Array
(
[4] => Array
(
[5] => Some nested value
)
)
)
)
)