PHP different 2 arrays and use conditions in comparison - php

I have 2 arrays follow this:
Array A
Array
(
[0] => Array
(
[TD_CODE] => 24203
[CRS_NAME] => Adobe Photoshop CS6+CC
)
[1] => Array
(
[TD_CODE] => 24202
[CRS_NAME] => Advance Microsoft excel 2010/2007
)
[2] => Array
(
[TD_CODE] => 24197
[CRS_NAME] => Beginning Auditor Tools and Techniques
)
);
And Array B
Array
(
[0] => Array
(
[crs_id] => 1
[crs_ia_id] => 2017-6495
[crs_oracle_id] => 24653
[crs_name] => Windows8
[crs_start_date] => 2017-08-07
[crs_end_date] => 2017-08-11
)
[1] => Array
(
[crs_id] => 2
[crs_ia_id] => 2017-5013
[crs_oracle_id] => 24202
[crs_name] => Advance Microsoft excel 2010/2007
[crs_start_date] => 2017-02-08
[crs_end_date] => 2017-02-09
)
)
I want to make array A different array B.
The condition is to use TD_CODE of the array A compared to crs_oracle_id of array b And and take it as array C.
So The results are as follows.
Array
(
[0] => Array
(
[TD_CODE] => 24203
[CRS_NAME] => Adobe Photoshop CS6+CC
)
[1] => Array
(
[TD_CODE] => 24197
[CRS_NAME] => Beginning Auditor Tools and Techniques
)
);
How should I do?

You can use array_filter() with anonymous function to compare TD_CODE and crs_oracle_id
$array_c = array_filter($array_a, function($e) use($array_b) {
foreach ($array_b as $v) {
if ($v['crs_oracle_id'] == $e['TD_CODE']) {
return false;
}
}
return true;
});
print_r($array_c);

Get ids from second array which needs to be rejected, then add only those records which doesn't exists in this id array,
$rejected_ids = array_column($b,'crs_oracle_id');
$c = [];
foreach($a as $v){
if(!in_array($v['TD_CODE'], $rejected_ids)){
$c[] = $v;
}
}
print_r($c);
array_column — Return the values from a single column in the input array
Here is working demo
EDIT
Here is more optimized code,
$c = array_filter($a, function($v,$k) use($rejected_ids){
return !in_array($v['TD_CODE'], $rejected_ids);
},ARRAY_FILTER_USE_BOTH);
Here is working demo.
array_filter — Filters elements of an array using a callback function
ARRAY_FILTER_USE_BOTH - pass both value and key as arguments to callback instead of the value

If your PHP Version is below 5.5 Then Please use this function
if (! function_exists('array_column')) {
function array_column(array $input, $columnKey, $indexKey = null) {
$array = array();
foreach ($input as $value) {
if ( !array_key_exists($columnKey, $value)) {
trigger_error("Key \"$columnKey\" does not exist in array");
return false;
}
if (is_null($indexKey)) {
$array[] = $value[$columnKey];
}
else {
if ( !array_key_exists($indexKey, $value)) {
trigger_error("Key \"$indexKey\" does not exist in array");
return false;
}
if ( ! is_scalar($value[$indexKey])) {
trigger_error("Key \"$indexKey\" does not contain scalar value");
return false;
}
$array[$value[$indexKey]] = $value[$columnKey];
}
}
return $array;
}
}
ARRAY - A
$array_a = Array
(
'0' => Array
(
'TD_CODE' => '24203',
'CRS_NAME' => 'Adobe Photoshop CS6+CC'
),
'1' => Array
(
'TD_CODE' => '24202',
'CRS_NAME' => 'Advance Microsoft excel 2010/2007'
),
'2' => Array
(
'TD_CODE' => '24197',
'CRS_NAME' => 'Beginning Auditor Tools and Techniques'
)
);
ARRAY - B
$array_b = Array
(
'0' => Array
(
'crs_id' => '1',
'crs_ia_id' => '2017-6495',
'crs_oracle_id' => '24653',
'crs_name' => 'Windows8',
'crs_start_date' => '2017-08-07',
'crs_end_date' => '2017-08-11'
),
'1' => Array
(
'crs_id' => '2',
'crs_ia_id' => '2017-5013',
'crs_oracle_id' => '24202',
'crs_name' => 'Advance Microsoft excel 2010/2007',
'crs_start_date' => '2017-02-08',
'crs_end_date' => '2017-02-09'
)
);
ARRAY - C
$array_c = array();
foreach ($array_a as $a){
if(!in_array($a['TD_CODE'], array_column($array_b, 'crs_oracle_id'))) {
$array_c[] = array('TD_CODE' => $a['TD_CODE'],'CRS_NAME'=>$a['CRS_NAME']);
}
}
print_r($array_c);

Related

Create smart recursive function for multidimensional array which returns all arrays inside in one array

The main thing is multidimensional arrays can be random and I don't know exactly how many arrays inside in it. That why function should include recursion and checks does it have more array inside, example below can't do it without pre configuration. Appreciating any help
$arrays = array(
array(
'House' => 'Baratheon',
'Sigil' => 'A crowned stag',
'Motto' => 'Ours is the Fury',
),
array(
'Leader' => 'Eddard Stark',
'House' => 'Stark',
'Motto' => 'Winter is Coming',
'Sigil' => 'A grey direwolf'
),
array(
array('SomeArray' => 'You are cool'),
'House' => 'Lannister',
'Leader' => 'Tywin Lannister',
'Sigil' => 'A golden lion'
),
array(
'Q' => 'Z'
)
);
function next_element($array) {
foreach ($array as $some_type) {
if (is_array($some_type)) {
return true;
} else {
return false;
}
}
}
function check_in($inputs) {
foreach ($inputs as $position => $input) {
if (is_array($input) && next_element($input)) { // case with multidimentional array
check_in($input);
$check_in_result[] = "There are should be recursion!!!!!";
} else { // case with one simple array
$check_in_result[] = $input;
}
}
return $check_in_result;
}
Have tried with array_walk_recursive() but that function is working with all elements and returns as result one array with all keys and values. In this case it should be array(array1, array2, array3, array4) for next stage which is foreach loop.
As resutl it should be:
Array
(
[0] => Array
(
[House] => Baratheon
[Sigil] => A crowned stag
[Motto] => Ours is the Fury
)
[1] => Array
(
[Leader] => Eddard Stark
[House] => Stark
[Motto] => Winter is Coming
[Sigil] => A grey direwolf
)
[2] => Array
(
[SomeArray] => You are cool
)
[3] => Array
(
[House] => Lannister
[Leader] => Tywin Lannister
[Sigil] => A golden lion
)
[4] => Array
(
[Q] => Z
)
)
Try using a recursive function like this:
function parseMyArray($array) {
$result = [];
$row = [];
foreach($array as $key => $item) {
if (is_array($item)) {
$result = array_merge($result, parseMyArray($item));
} else {
$row[$key] = $item;
}
}
return !empty($row) ? array_merge($result, [$row]) : $result;
}
$result = parseMyArray($arrays);
print_r($result);
At each level of a function call, all scalar values with their keys are collected into one array as $row and merged with the $result of a nested function call.
fiddle

How to read nested array values without knowing the keys?

I'm new in array. I wish to print out the values of all possible [type] [label] [value]. I wish to do like "if there's a type with select, then display all labels with values"
Below is my array.
Array
(
[product_id] => 8928
[title] => Example of a Product
[groups] => Array
(
[8929] => Array
(
[8932] => Array
(
[type] => select
[label] => Section
[id] => pewc_group_8929_8932
[group_id] => 8929
[field_id] => 8932
[value] => Section 200
[flat_rate] => Array
(
)
)
)
)
[price_with_extras] => 0
[products] => Array
(
[field_id] => pewc_group_8929_9028
[child_products] => Array
(
[8945] => Array
(
[child_product_id] => Array
(
[0] => 8945
)
[field_id] => pewc_group_8929_9028
[quantities] => one-only
[allow_none] => 0
)
)
[pewc_parent_product] => 8928
[parent_field_id] => pewc_5d678156d81c6
)
)
The site is saying "
It looks like your post is mostly code; please add some more details." So here's my so-called lorem ipsum :D
You can use array_walk_recursive for the same,
array_walk_recursive($arr, function ($value, $key) {
// check if key matches with type, label or value
if (count(array_intersect([$key], ['type', 'label', 'value'])) > 0) {
echo "[$value] ";
}
});
Demo
Output
[select] [Section] [Section 200]
EDIT
You can modify the condition as,
if($key === 'type' && $value == 'select')
EDIT 1
array_walk_recursive($arr, function ($value, $key) {
if($key === 'type' && $value == 'select'){
echo "[$value] ";
}
});
EDIT 2
function search_by_key_value($arr, $key, $value)
{
$result = [];
if (is_array($arr)) {
if (isset($arr[$key]) && $arr[$key] == $value) {
$result[] = $arr;
}
foreach ($arr as $value1) {
$result = array_merge($result, search_by_key_value($value1, $key, $value));
}
}
return $result;
}
// find array by key = type and value = select
$temp = search_by_key_value($arr, 'type', 'select');
$temp = array_shift($temp);
print_r($temp);
echo $temp['label'];
echo $temp['value'];
Demo

How to filter a two dimensional array by value

How would I create a function that filters a two dimensional array by value?
Given the following array :
Array
(
[0] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => CarEnquiry
[status] => NEW
[appointment] => 0
)
[1] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => CarEnquiry
[status] => CALL1
[appointment] => 0
)
[2] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => Finance
[status] => CALL2
[appointment] => 0
)
[3] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => Partex
[status] => CALL3
[appointment] => 0
)
How would I filter the array to only show those arrays that contain a specific value in the name key? For example name = 'CarEnquiry'.
The resulting output would be:
Array
(
[0] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => CarEnquiry
[status] => NEW
[appointment] => 0
)
[1] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => CarEnquiry
[status] => CALL1
[appointment] => 0
)
)
EDIT
I forgot to mention that the search value should be interchangeable - i.e. name = 'CarEnquiry' or name = 'Finance'.
Use PHP's array_filter function with a callback.
$new = array_filter($arr, function ($var) {
return ($var['name'] == 'CarEnquiry');
});
Edit: If it needs to be interchangeable, you can modify the code slightly:
$filterBy = 'CarEnquiry'; // or Finance etc.
$new = array_filter($arr, function ($var) use ($filterBy) {
return ($var['name'] == $filterBy);
});
If you want to make this a generic function use this:
function filterArrayByKeyValue($array, $key, $keyValue)
{
return array_filter($array, function($value) use ($key, $keyValue) {
return $value[$key] == $keyValue;
});
}
<?php
function filter_array($array,$term){
$matches = array();
foreach($array as $a){
if($a['name'] == $term)
$matches[]=$a;
}
return $matches;
}
$new_array = filter_array($your_array,'CarEnquiry');
?>
Above examples are using the exact word match, here is a simple example for filtering array to find imprecise "name" match.
$options = array_filter($options, function ($option) use ($name) {
return strpos(strtolower($option['text']), strtolower($name)) !== FALSE;
});
array_filter is the function you need. http://php.net/manual/en/function.array-filter.php
Give it a filtering function like this:
function my_filter($elt) {
return $elt['name'] == 'something';
}
function multi_array_search_with_condition($array, $condition)
{
$foundItems = array();
foreach($array as $item)
{
$find = TRUE;
foreach($condition as $key => $value)
{
if(isset($item[$key]) && $item[$key] == $value)
{
$find = TRUE;
} else {
$find = FALSE;
}
}
if($find)
{
array_push($foundItems, $item);
}
}
return $foundItems;
}
This my function can use about this problem. You can use:
$filtered = multi_array_search_with_condition(
$array,
array('name' => 'CarEnquiry')
);
This will get your filtered items from your 2 dimensional array.

grabbing only certain array inside array

Basically, I'm receiving an array() from the Yahoo Messenger API in PHP and am in the process of developing an notification system, It returns an array with both the IM received from an chat and my contacts.
Array (
[0] => Array
(
[message] => Array
(
[status] => 1
[sequence] => 0
[sender] => SenderCurtis
[receiver] => receiverCurtis
[msg] => #1
[timeStamp] => 1374187598
[hash] => y2qlDf8uTq8tXzgzrsSMyjQB+W2uDg==
[msgContext] => y2qlDf8uTq8tXzgzrsSMyjQB+W2uDg==
)
)
[1] => Array
(
[buddyInfo] => Array
(
[sequence] => 1
[contact] => Array
(
[0] => Array
(
[sender] => SenderCurtis
[presenceState] => 0
[avatarUser] => 0
[avatarPreference] => 0
[clientCapabilities] => 8915971
[clientUserGUID] => MI7STHUYOAMCGE5TNTY7CJPFWM
)
)
)
)
[2] => Array
(
[message] => Array
(
[status] => 1
[sequence] => 2
[sender] => SenderCurtis
[receiver] => receiverCurtis
[msg] => #2
[timeStamp] => 1374187601
[hash] => 3+2s9sIvjPRdvneQsMgVNCKBTFgKwQ==
[msgContext] => 3+2s9sIvjPRdvneQsMgVNCKBTFgKwQ==
)
)
[3] => Array
(
[buddyInfo] => Array
(
[sequence] => 3
[contact] => Array
(
[0] => Array
(
[sender] => myContactUser1#yahoo.com
[presenceState] => 0
[avatarUser] => 0
[avatarPreference] => 0
[clientCapabilities] => 8915971
[clientUserGUID] => UQU3WV7ZOZ2OTGLJQUE2QJU4ZU
)
)
)
)
)
How can I grab just the message array() and iterate through it? such as "Message 1", "Message2" etc...
If you're trying to filter the array values for the key 'message', you could do something like this in PHP:
$messages = array();
foreach ($response as $key => $data) {
if (array_key_exists('message', $data)) {
$msgArray = $data['message'];
$messages[] = $msgArray;
}
}
In the above sample, I'm storing the messages in their own array. But you could process the data right inside the for-loop too, if you want that.
I think that array_map() is the function you are looking for here. The array_map function allows you to execute a callback on each element of an existing array and assemble a new array consisting only of the values returned by the callback.
What you would want to do is something like this :
$data = // lets assume this is the data you received
$messages_data = array_map( "extract_message", $data );
function extract_message( $data_item ){
if ( array_key_exists( 'message', $data_item ) ){
return $data_item[ 'message' ];
}
}
Now your $message_data array will contain only the message arrays from the original array.
foreach ($var[0] as $key => $value)
{
do things with each message
}
where $var is substituted for your actual variable name
Just filter your array using array_filter.
$messages = array_filter($data, function($a){ return isset($a["message"]); });
Then use array_map to get rid of the unwanted intermediate array.
$messages = array_map(function($a){ return $a["message"]; }, $message);
then you can iterate over it with a foreach or whatever.
Because I like SPL iterators here another solution. Works with PHP >= 5.1.0.
class MessageIterator extends FilterIterator
{
public function accept()
{
return array_key_exists('message', $this->getInnerIterator()->current());
}
public function current()
{
$current = parent::current();
return $current['message'];
}
}
$iterator = new MessageIterator(new ArrayIterator($array));
foreach ($iterator as $message) {
print_r($message);
}

Sorting an array according to some duplicate values in PHP

I have an array containing strings of this format:
[0] => "title|url|score|user|date"
[1] => "title|url|score|user|date"
[2] => "title|url|score|user|date"
[3] => "title|url|score|user|date"
...
The score field is an int that is not always unique (for example, more than one entry can have a score of 0). I'm looking to sort the strings in this array based on their score value. Originally, I tried iterating through the array and making a new one with keys corresponding to the vote score. I soon realized that you can't have duplicate keys in an array.
Is there a good clean way of doing this?
$array = array(
0 => "title|url|12|user|date",
1 => "title|url|0|user|date",
2 => "title|url|13|user|date",
3 => "title|url|0|user|date"
);
function sortOnScore( $a, $b )
{
// discard first two values
list( ,,$scoreA ) = explode( '|', $a );
list( ,,$scoreB ) = explode( '|', $b );
return $scoreA == $scoreB ? 0 : ( $scoreA > $scoreB ? 1 : -1 );
}
usort( $array, 'sortOnScore' );
var_dump( $array );
Look into PHP's usort function
function score_sort($rec1, $rec2)
{
return $rec1['score'] - $rec2['score'];
}
usort($score_array);
Replace ['score'] with however you are extracting the scores from the strings
First you need to turn the strings into arrays with explode so you can do the comparisons:
// If using PHP >= 5.3, this can also be made into an anonymous function
function converter($string) {
$result = array_combine(
array('title', 'url', 'score', 'user', 'date'),
explode('|', $string)
);
// When these are later compared, it should be as numbers
$result['score'] = (int)$result['score'];
return $result;
}
$input = array(
'Foo|http://foo|0|user1|today',
// etc.
);
$converted = array_map('converter', $input);
This will make $converted look like:
array (
0 => array (
'title' => 'Foo',
'url' => 'http://foo',
'score' => '0',
'user' => 'user1',
'date' => 'today',
),
)
Then you can sort the array using the code from my answer here by easily specifying any sort criteria you want:
usort($converted, make_converter('score', 'date', 'title'));
Personally I'd be tempted to iterate through the array, split it by the |'s and put it into a new multi-dimensional array, for example something like this:
[0] => array([title]=>'title',[url]=>'url',[score]=>'score',[user]=>'user',[date]=>'date')
[1] => array([title]=>'title',[url]=>'url',[score]=>'score',[user]=>'user',[date]=>'date')
Then it becomes easy to sort, just use a function like this:
function sortmulti ($array, $index, $order, $natsort=FALSE, $case_sensitive=FALSE) {
if(is_array($array) && count($array)>0) {
foreach(array_keys($array) as $key) {
$temp[$key]=$array[$key][$index];
}
if(!$natsort) {
if ($order=='asc') {
asort($temp);
} else {
arsort($temp);
}
}
else
{
if ($case_sensitive===true) {
natsort($temp);
} else {
natcasesort($temp);
}
if($order!='asc') {
$temp=array_reverse($temp,TRUE);
}
}
foreach(array_keys($temp) as $key) {
if (is_numeric($key)) {
$sorted[]=$array[$key];
} else {
$sorted[$key]=$array[$key];
}
}
return $sorted;
}
return $sorted;
}
i.e. do this:
$sortedarray = sortmulti($array,'score','asc');
It would be very easy using the asort function:
$pattern = '#^([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)$#';
$sorted = array();
foreach($data as $s) $sorted[] = preg_replace($pattern, '$3|$1|$2|$4|$5', $s);
asort($sorted);
these 4 lines of code, when given $data:
Array
(
[0] => title_0|url_0|6|user_0|date_0
[1] => title_1|url_1|6|user_1|date_1
[2] => title_2|url_2|2|user_2|date_2
[3] => title_3|url_3|3|user_3|date_3
[4] => title_4|url_4|2|user_4|date_4
[5] => title_5|url_5|7|user_5|date_5
[6] => title_6|url_6|3|user_6|date_6
[7] => title_7|url_7|8|user_7|date_7
[8] => title_8|url_8|3|user_8|date_8
[9] => title_9|url_9|9|user_9|date_9
)
will generate $sorted:
Array
(
[2] => 2|title_2|url_2|user_2|date_2
[4] => 2|title_4|url_4|user_4|date_4
[3] => 3|title_3|url_3|user_3|date_3
[6] => 3|title_6|url_6|user_6|date_6
[8] => 3|title_8|url_8|user_8|date_8
[0] => 6|title_0|url_0|user_0|date_0
[1] => 6|title_1|url_1|user_1|date_1
[5] => 7|title_5|url_5|user_5|date_5
[7] => 8|title_7|url_7|user_7|date_7
[9] => 9|title_9|url_9|user_9|date_9
)
and with just 2 more lines you can have the items in each element of the array back in the original order/format:
$data = array();
foreach($sorted as $s) $data[] = preg_replace($pattern, '$2|$3|$1|$4|$5', $s);
setting $data to:
Array
(
[0] => title_2|url_2|2|user_2|date_2
[1] => title_4|url_4|2|user_4|date_4
[2] => title_3|url_3|3|user_3|date_3
[3] => title_6|url_6|3|user_6|date_6
[4] => title_8|url_8|3|user_8|date_8
[5] => title_0|url_0|6|user_0|date_0
[6] => title_1|url_1|6|user_1|date_1
[7] => title_5|url_5|7|user_5|date_5
[8] => title_7|url_7|8|user_7|date_7
[9] => title_9|url_9|9|user_9|date_9
)
Create a new array of arrays:
[0] => array("score", old_array[0])
Then sort.

Categories