Perl 2D array comparison issues - performance

I'm coding a perl script that audits a library and compares the list of installed software with a list from another machine to ensure that they are working off of the same stuff. I've taken the raw data and placed it into two, 2-dimensional arrays of size Nx4 where N is the number of software titles. For example:
[Fileset1], [1.0.2.3], [COMMITTED], [Description of file]
[Fileset2], [2.4.2.2], [COMMITTED], [Description of a different file]
....
I now need to compare the two lists to find discrepancies, whether they be missing files of level differences. Not being a perl pro yet, the only way I can conceive of doing this is to compare each element of the first array against each element of the other array to look first for matching filesets with different levels or no matching filesets at all. The I would have to repeat the process with the other list to ensure that I'd found all possible differences. Obviously with this procedure I'm looking at efficiency of greater than n^2. I was wondering if there was some application of grep that I could make use of or something similar to avoid this when comparing libraries with upwards of 20,000 entries.
In short, I need to compare two 2 dimensional arrays and keep track of the differences for each list, instead of merely finding the intersection of the two.
Thanks in advance for the help!

The output is a little unwieldy, but I like Data::Diff for tasks like this:
use Data::Diff 'Diff';
use Data::Dumper;
#a = ( ["Fileset1", "1.0.2.3", "COMMITTED", "Description of file" ],
["Fileset2", "2.4.2.2", "COMMITTED", "Description of a different file" ],
["Fileset3", "1.2.3.4", "COMMITTED", "Description of a different file" ] );
#b = ( ["Fileset1", "1.0.2.3", "COMMITTED", "Description of file" ],
["Fileset2", "2.4.2.99", "COMMITTED", "Description of a different file" ] );
$out = Diff(\#a,\#b);
print Dumper($out);
Result:
$VAR1 = {
'diff' => [
{
'uniq_a' => [
'2.4.2.2'
],
'same' => [
{
'same' => 'COMMITTED',
'type' => ''
},
{
'same' => 'Description of a different file',
'type' => ''
},
{
'same' => 'Fileset2',
'type' => ''
}
],
'type' => 'ARRAY',
'uniq_b' => [
'2.4.2.99'
]
}
],
'uniq_a' => [
[
'Fileset3',
'1.2.3.4',
'COMMITTED',
'Description of a different file'
]
],
'same' => [
{
'same' => [
{
'same' => '1.0.2.3',
'type' => ''
},
{
'same' => 'COMMITTED',
'type' => ''
},
{
'same' => 'Description of file',
'type' => ''
},
{
'same' => 'Fileset1',
'type' => ''
}
],
'type' => 'ARRAY'
}
],
'type' => 'ARRAY'
};

Related

Problem with Collection::sortBy() in cakephp 4

I'm trying to sort a list of email accounts by alphabetical order using Collection::sortBy() in cakephp 4, but it seems not working the way I use it.
$accounts = [
[
'email' => 'webmaster#example.com',
'isBlocked' => false,
],
[
'email' => 'dom#example.com',
'isBlocked' => false,
],
[
'email' => 'me#example.com',
'isBlocked' => false,
],
[
'email' => 'guy#example.com',
'isBlocked' => false,
],
[
'email' => 'test#example.com',
'isBlocked' => false,
]
];
$sorted = collection($accounts)
->sortBy('email', SORT_ASC)
->toArray();
debug($sorted);
debug($sorted) returns exactly the same array as $accounts...
What am I doing wrong ?
The default sort type is SORT_NUMERIC, and converted to numbers, all your strings will be 0, hence all are equal as seen by the sorting mechanism, and nothing will chance.
For strings use SORT_NATURAL, SORT_STRING, SORT_LOCALE_STRING, or SORT_REGULAR, eg:
sortBy('email', SORT_ASC, SORT_NATURAL)
The Cookbook needs a fix there I think, as it shows referencing string fields without specifying the required sort type.
See also
PHP Manual > Function Reference > Variable and Type Related Extensions > Arrays > Array Functions > sort
Cookbook > Collections > Sorting

How to test array contains only objects with PHPUnit?

I'm looking for solution to test an array of objects with PHPUnit in my Laravel project.
This is my haystack array:
[
[
"id" => 10,
"name" => "Ten"
],
[
"id" => 5,
"name" => "Five"
]
]
And this is the needles array:
[
[
"id" => 5,
"name" => "Five"
],
[
"id" => 10,
"name" => "Ten"
]
]
The order of objects doesn't matter, also keys of objects doesn't matter. The only matter is we have two objects and all objects has exactly same keys and exactly same values.
What is the correct solution for this?
You can do this using the assertContainsEquals method like this:
$haystack = [
[
'id' => 10,
'name' => 'Ten'
],
[
'id' => 5,
'name' => 'Five'
]
];
$needles = [
[
'name' => 'Five',
'id' => 5
],
[
'id' => 10,
'name' => 'Ten'
]
];
foreach ($needles as $needle) {
$this->assertContainsEquals($needle, $haystack);
}
You could also a create your own assert method if you intend to perform the assertion more often:
public function assertContainsEqualsAll(array $needles, array $haystack): void
{
foreach ($needles as $needle) {
$this->assertContainsEquals($needle, $haystack);
}
}
Based on #Roj Vroemen's answer I implemented this solution for exact match asserting:
public function assertArrayContainsEqualsOnly(array $needles, array $haystack, string $context = ''): void
{
foreach ($needles as $index => $needle) {
$this->assertContainsEquals(
$needle,
$haystack,
($context ? $context . ': ' : '') . 'Object not found in array.'
);
unset($haystack[$index]);
}
$this->assertEmpty(
$haystack,
($context ? $context . ': ' : '') . 'Not exact match objects in array.'
);
}

Laravel - Pluck multiple columns

I need to pluck two columns name and score from my table corporate_objectives and put it in my graph chart. I'm having two different behavior and I can't seem to get my desired result.
1st code
$getNameAndScore = CorporateObjective::pluck('name');
foreach($getNameAndScore as $key => $item) {
$corporateObjective[] = [$item, '('.$key.'%)'];
}
Result:
"xAxis": [
[
"PEOPLE DEVELOPMENT",
"(0%)"
],
[
"OPTIMUM SYSTEMS AND PROCESSES",
"(1%)"
],
[
"CUSTOMER MANAGEMENT",
"(2%)"
],
[
"REVENUE GROWTH",
"(3%)"
]
],
2nd code
$getNameAndScore = CorporateObjective::pluck('name', 'score');
foreach($getNameAndScore as $key => $item) {
$corporateObjective[] = [$item, '('.$key.'%)'];
}
Result:
"xAxis": [
[
"REVENUE GROWTH",
"(25%)"
]
],
I'm getting all the correct name but the incorrect score in my first code. On my second code, I'm getting the correct name and score but all data is not being pulled out. I wanted to achieve the first code with all the correct score from the second code.
EDIT:
This is how my database looks like
id | name | score
1 PEOPLE DEVELOPMENT 25
2 OPTIMUM SYSTEMS AND PROCESSES 25
3 CUSTOMER MANAGEMENT 25
4 REVENUE GROWTH 25
Is there another way other than pluck? It seems like pluck merges / filters all data with the same value.
This is the correct output of your code. There is no problem here
$getNameAndScore = CorporateObjective::pluck('name', 'score');
foreach($getNameAndScore as $key => $item) {
$corporateObjective[] = [$item, '('.$key.'%)'];
}
How does work pluck here is description
If duplicate keys exist, the last matching element will be inserted into the plucked collection:
$collection = collect([
['brand' => 'Tesla', 'color' => 'red'],
['brand' => 'Pagani', 'color' => 'white'],
['brand' => 'Tesla', 'color' => 'black'],
['brand' => 'Pagani', 'color' => 'orange'],
]);
$plucked = $collection->pluck('color', 'brand');
$plucked->all();
// ['Tesla' => 'black', 'Pagani' => 'orange']
Details in here
So I just made an alternative way of doing it and it might help other people. If there is a more proper way or cleaner way of doing it, please feel free to correct my answer.
$getNameAndScore = CorporateObjective::pluck('name');
foreach($getNameAndScore as $item) {
$key = CorporateObjective::where('name', $item)->value('score');
$corporateObjective[] = [$item, '('.$key.'%)'];
}
return response()->json([
'xAxis' => $corporateObjective,
]);
Result
"xAxis": [
[
"PEOPLE DEVELOPMENT",
"(25%)"
],
[
"OPTIMUM SYSTEMS AND PROCESSES",
"(1%)" // I changed the value in the database and it works
],
[
"CUSTOMER MANAGEMENT",
"(22%)" // I changed the value in the database and it works
],
[
"REVENUE GROWTH",
"(25%)"
]
],

Require Elasticsearch highlight words enclosed with Double Quotes (") instead of chopping them

Elasticsearch: v7.2
Application: PHP - Laravel v5.7
Hello and good day!
I'm developing a web application that is similar to a search engine, whereas a user will enter words that will be designated to the variable $keywords. Then I have this query to search throughout my index:
$params = [
'index' => 'my_index',
'type' => 'my_type',
'from' => 0,
'size' => 10,
'body' => [
"query" => [
'bool' => [
'must' => [
[
"query_string" => [
"fields" => ['title','content'],
"query" => $keywords
]
]
]
]
]
]
];
$articles = $client->search($params);
Now, in line with my previous post, I was able to count the number of occurrences my $keywords occurred within the documents of my index.
Here's my highlight query that is attached to the $params above:
"highlight" => [
"fields" => [
"content" => ["number_of_fragments" => 0],
"title" => ["number_of_fragments" => 0]
]
'require_field_match' => true
]
Even though that the $keywords are enclosed with double quotation mark ("), the highlighter still chops/separates the $keywords and I already specified them with double quotation mark to strictly follow these words.
For example, my $keywords contains "Ayala Alabang", but as I displayed the output, it goes like this
The $keywords were separated, but according to the output, they're just adjacent to each other.
Is there any other tweaks or revision to my query? I found some related posts or questions in some forums, their last reply was from March 2019, any advice would be an excellent help for this dilemma
After a few days of looking into deep documentation, I found a way to properly segregate keywords that are found in a document
STEP 1
Apply the "explain" => true in your $params
$params = [
'index' = "myIndex",
'type' => "myType",
'size' => 50,
'explain' => true,
'query' => [
'match_all' => [
//your elasticearch query here
]
]
]
STEP 2
Then fetch the result after doing the $client->search($params) code:
$result = $client->search($params);
Then a long literal EXPLANATION will be included in your $result whereas your keywords and their frequency will be displayed in a text format.:
try displaying via dd($result['explanation'])
NOTE the problem here is that a lot of nested arrays will be the contents of the _explanation array key, so we came up with a recursive function to look for the keywords and their frequency
STEP 3
You need to create a function that will get a string IN BETWEEN of repetitive or other strings:
public static function get_string_between($string, $start, $end){
$string = ' ' . $string;
$ini = strpos($string, $start);
if ($ini == 0) return '';
$ini += strlen($start);
$len = strpos($string, $end, $ini) - $ini;
return substr($string, $ini, $len);
}
STEP 4
Then create the recursive function:
public static function extract_kwds($expln,$kwds)
{
foreach($expln as $k=>$v)
{
if($k == 'description' && strpos(json_encode($v),'weight(')!==false)
{
if(isset($kwds[$this->get_string_between($v,':',')')]))
{
$kwds[$this->get_string_between($v,':',')')] += intVal($this->get_string_between($expln['details'][0]['description'],'score(freq=',')'));
}
else
{
$kwds[$this->get_string_between($v,':',')')] = intVal($this->get_string_between($expln['details'][0]['description'],'score(freq=',')'));
}
}
if($k == 'details' && count($v) != 0)
{
foreach($v as $k2=>$v2)
{
$kwds = $this->extract_kwds($v2,$kwds);
}
}
}
return $kwds;
}
FINALLY
I was able to fetch all the keywords together with their frequency or how many times these keywords appeared in the documents.

!empty record show in first order in cake php

I have a retrieved restaurant list. when the restaurant menu is empty that restaurant showed in last order.. what i do.. can you help..
My Query is :
$restaurantList = $this->Restaurants->find('all', [
'conditions' => $conditions,
'contain' => [
'DeliveryLocations' => [
'conditions' => $areaLocationConditions,
],
'RestaurantMenus' => [
'conditions' => [
'RestaurantMenus.status' => 1,
'RestaurantMenus.delete_status' => 'N'
]
]
],
'limit' => 5,
'order' => 'Restaurants.id DESC'
])->hydrate(false)->toArray();
Simple solution:
by implementing CounterCache
https://book.cakephp.org/3.0/en/orm/behaviors/counter-cache.html and order by cache results.
More complex:
by using Case statements
https://book.cakephp.org/3.0/en/orm/query-builder.html#case-statements
select 'has_menus' if restuarant has menus then 1 else 0
order by that results

Resources