Get difference in an array in PHP - php

In my scenario a paintings list is located in the column in json format. Paintings list contains file name, painting name and view count. I want to delete a painting in the list. But I did not manage. Here is my codes:
$paintings = '[["24ef9-70076-4358c-48386.jpg","La Donna Gravida","649"],["a7972-065a9-4c0f9-723d1.jpg","Madonna and Child with the Book","1254"],["b054c-df208-0f600-e884e.jpg","Madonna del Granduca","1457"]]';
$painting = 'a7972-065a9-4c0f9-723d1.jpg';
$difference = array_diff((array)json_decode($paintings), (array)$painting);
echo json_encode(array_values($difference));
I am trying to reach the following conclusion: [["24ef9-70076-4358c-48386.jpg","La Donna Gravida","649"],["b054c-df208-0f600-e884e.jpg","Madonna del Granduca","1457"]] But I get error like this: Notice: Array to string conversion in... Could you help me?

You do not have objects with keys in the json string, so the array you create by decoding it will not be associative with keys. One of the possible ways to solve your problem is shown below (straight forward one).
$out = array();
foreach(json_decode($paintings, true) as $p)
if (!in_array($painting, $p))
$out[] = $p;
echo json_encode(array_values($out));
Another way
$out = array_filter(json_decode($paintings, true), function($el) use($painting) {
return !in_array($painting, $el);
});
echo json_encode(array_values($out));
The reason is because ["a7972-065a9-4c0f9-723d1.jpg","Madonna and Child with the Book","1254"] is not an element with key or value a7972-065a9-4c0f9-723d1.jpg - it is another array and you have to check either the existence of the value in the whole sub-array or just its first element. In that case !in_array($painting, $el) can be replaced by $painting != $el[0]

Related

Foreach loop over array of objects Laravel

I'm receiving this array of objects and need to iterate over it, but the problem is that I need to get the value of the next item when its iterating, to compare the value of the current object with the next one, and if it's a different value, split this array in two.
So, I was doing it with next() php function:
//looking for the next register in the array
$next = next($finances);
//first array if exist different values
$aiuaEd = [];
//second array if exist different values
$aiua = [];
foreach ($finances as $finance) {
if ($finance->cnpj <> $next->cnpj) {
$aiua[] = $finance;
} else {
$aiuaEd[] = $finance;
}
}
This code works fine at some point, but then I got this error:
Trying to get property 'cnpj' of non-object in
I don't know why sometimes works well and sometimes don't, debugging this variables, I found that if my array have 2 objects inside only, when I'm looping over it, the $next->cnpj variable came as empty, and sometimes don't.
Can someone help me with this?
I solved it with a different approach, instead of using php next(), I first loop over this array saving the cnpj's into an array.
$cnpjs = [];
foreach($finances as $finance){
$cnpj[] = $finance->cnpj;
}
Then I use array_unique() to group this 2 differents CNPJ's and sort() to get the correct keys order.
//grouping cnpjs as unique, should exist only 2 keys
$cnpj = array_unique($cnpj);
//sort array keys to get in order
sort($cnpj);
Then I iterate over my $finances array again, but now I'm counting if this $cnpj array has more than 2 positions, which means that I have to split this data in two differents arrays.
foreach($finances as $finance){
if(count($cnpj) > 1){
if($finance->cnpj == $cnpj[1]){
$aiua[] = $finance;
}else{
$aiuaEd[] = $finance;
}
}else{
$aiuaEd[] = $finance;
}
}
I'm pretty sure that this is not the best approach for that problem, or at least the most optimized one, so I'm open for new approach's suggestions!
Just posting how I solved my problem in case anyone having the same one.
Notice that this approach is only usable because I know that will not exist more than 2 different's CNPJ's in the array.

PHP Loop array object once, or wild card key?

I have a php array, and inside the array is a reference to another php object with a numerical value.
How can i access the elements in this array without knowing that numerical id (it could be different for each array)?
In the image below, I need to get the values inside field_collection_item like so....
$content['field_image_columns'][0]['entity']['field_collection_item'][133]['field_image']
For the first array key (0) i have done the following...
$i = 0;
while($i <= 2) {
if(isset($content['field_image_columns'][$i])) {
print '<div class="column-' . $i . '">';
foreach ($content['field_image_columns'][$i]['entity']['field_collection_item'] as $fcid => $values) {
// Print field values
}
print '</div>';
}
$i++;
}
Doing a foreach loop for a single array item seems wrong - is there a method i should be using for this use case?
You can select first item of array for example with:
Use array_shift, but it will modify source array:
$cur = array_shift($content['field_image_columns'][$i]['entity']['field_collection_item']);
print $cur['field_image'];
Get keys of array with array_keys and use first element of result as a key
$ks = array_keys($content['field_image_columns'][$i]['entity']['field_collection_item']);
print $content['field_image_columns'][$i]['entity']['field_collection_item'][$ks[0]]['field_image'];
Use current function:
$cur = current($content['field_image_columns'][$i]['entity']['field_collection_item']);
print $cur['field_image'];
As with most programming, there are quite a few ways you could do it. If a foreach works, then it isn't wrong, but it may not be the best way.
// Get the current key from an array
$key = key($array);
If you don't need the key, then you can just get the value from the array.
// Get the current value from an array
$value = current($array);
Both of these will retrieve the first key/value from the array assuming you haven't advanced the pointer.
current, key, end, reset, next, & prev are all array functions that allow you to manipulate an array without knowing anything about the internals. http://php.net/manual/en/ref.array.php

Get Records From Array Based On Value

Bottom line, I have a huge multidimensional array returned by ldap_get_entries that I am trying to parse into different groups based on the location attribute.
In PowerShell I could do something like:
$location1 = Get-ADUser -Filter * | ? {?_.l -eq "test_location"}
What I am currently doing within PHP (as far as my brain will let me go) is something like:
Foreach ($records as $record) {
if (isset($record['l'])) {
switch ($record['l'][0]) {
case "test_location1":
$location1[] = $record;
continue 2;
case "test_location2":
$location2[] = $record;
continue 2;
}
}
}
I then use a foreach loop (alternative syntax) against an array of location variables ($location1, $location2), that I used the above method, to sort records into their appropriate location variable. In this way, I build an HTML table grouping each locations records together. I build a new table for each location with some HTML code in between each group, so I don't believe sorting the ldap results by location will work, as it would output one large table.
Is there any way to specify a WHERE clause in PHP? So that I can assign all records in an array with a matching key value to variable1 and all records in an array with a different matching key value to variable2.
I am assuming I am tackling this in an amateur scripting way.. If there is an easier way to accomplish this task (maybe skipping the assign records to variables part), or any sort of "best practice" I am missing here, I am up for learning it.
Thanks in advance!!
As far as I understood your question you want something like this:
$recordsSorted = array();
foreach ($records as $record) {
if (! isset($record['l'])) {
continue;
}
$recordsSorted[$records['l'][0]][] = $record;
}
ksort($recordsSorted);
foreach($recordsSorted as $location => $records) {
usort($records, function($a, $b){
return strnatcasecmp($a['uid'][0], $b['uid'][0]);
});
echo '<h1>$location</h1><ul>';
foreach ($records as $record) {
echo '<li>' . $record['dn'] . '</li>';
}
echo '</ul>';
}
This will first put the first entry to the location-attribute of an entry as key of an array. That key can then be used to sort the array.
To output the content then it iterates over the new array and sorts the content - in this case using the first value of the uid-attribute (change the uid to whatever attribute you need). This sorted content is then output to HTML.
the first array $recordsSorted might look somewhat like this:
array(
'London' => array(
array(<entry from the LDAP>),
array(<another entry from LDAP>),
),
'Paris' => array(
array(<a further entry from the LDAP>),
),
'Berlin' => array(
array(<and even another entry from the LDAP>),
),
);
The result would then look somewhat like this:
<h1>Berlin</h1>
<ul>
<li>[UID of and even another entry from the LDAP]</li>
</ul>
<h1>London</h1>
<ul>
<li>[UID of another entry from LDAP]</li>
<li>[UID of entry from the LDAP]</li>
</ul>
<h1>Paris</h1>
<ul>
<li>[UID of a further entry from the LDAP]</li>
</ul>
Does that look like it could help you?

PHP spontaneously creates associative array where indexed array is required - using PHP arrays with Highcharts

I'm using PHP to retrieve data from an SQL database to produce a stacked column chart in Highcharts. The idea is that I'm taking the following piece of code to retrieve values from my database. This code should generate an array which then gets encoded to JSON and passed to Highcharts; this code produces a single 'part' of a stacked column, and the index determines which vertical bar that part is in. (So in http://www.highcharts.com/demo/column-stacked, the index would represent which fruit, and the data in this series would represent one person/color.)
The issue is that when I run this code, instead of ending up with an indexed array of data grouped by category, such as
[12,13,14,15] where each item is a category, I end up with an associative array where the indexes I specified in the code are turned into a string key.
{"1":13,"0":12,"3":14, "2":13, "5":15}
Because my indexes are being interpreted as associative keys and not as the indexed locations of the data inside the array, the data is now being added to locations in the order that I retrieved the data, and not assigned to a location in the array based on the index I give. Highcharts assigns categories based on location in the array, and not on key, so all my data ends up in the wrong categories.
Is there a way to get PHP to treat my carefully collected indexes as indexes and not as keys, and add my data points in the location in the array indicated by the indexes? I'm kind of new to PHP, and Java and C++ - the languages I've worked with before - don't have associative arrays, so any help you can give me in explaining and fixing this undesired behavior would be much appreciated.
Code below.
$variable indicates what the data is being sorted into categories by, and $r is the variable representing the array of the SQL query, so $r['variable'] is the category of this data point, and $r['amount'] is the data point itself.
$found = -1;
//if this is the first set of data being collected
if (count($category['data']) == 0){
$category['data'][0] = $r[$variable];
$series1['data'][0] = floatval($r['amount']);
$count++;
$times1[0]++;
}
//if it's not the first set of data, find out if this category has been used before
else {
for ($x = 0; $x < count($category['data']); $x++){
if ($r[$variable] == $category['data'][$x]){
$found = $x;
break;
}
}
// if that category does not already exist, add it, and add the data
if ($found == -1) {
$times1[$count]++;
$category['data'][$count] = $r[$variable];
$series1['data'][$count] = floatval($r['amount']);
$count++;
}
else { //otherwise, add its data to the data already in the current category. This will eventually yield an average, with $times1[] as the divisor
$times1[$found]++;
$series3['data'][$found] = floatval((floatval($series3['data'][$found]) + floatval($r['amount'])));
}}
Go through with below code hope it will give some idea to resolve your problem --
<?php
$jsonstring = '{"1":13,"0":12,"3":14, "2":13, "5":15}';
$tempArr = json_decode($jsonstring, true);
asort(tempArr); // for sorting the array --
//run another foreach to get created an array --
$finArr = array();
foreach(tempArr as $key=>$val){
$finArr[] = $val;
}
$requiredjsonString = json_encode(finArr); // it will return your required json Array [12,13,14,15]
?>
Edit: I advice also set JSON_NUMERIC_CHECK flag in json_encode();

Find index of value in associative array in php?

If you have any array $p that you populated in a loop like so:
$p[] = array( "id"=>$id, "Name"=>$name);
What's the fastest way to search for John in the Name key, and if found, return the $p index? Is there a way other than looping through $p?
I have up to 5000 names to find in $p, and $p can also potentially contain 5000 rows. Currently I loop through $p looking for each name, and if found, parse it (and add it to another array), splice the row out of $p, and break 1, ready to start searching for the next of the 5000 names.
I was wondering if there if a faster way to get the index rather than looping through $p eg an isset type way?
Thanks for taking a look guys.
Okay so as I see this problem, you have unique ids, but the names may not be unique.
You could initialize the array as:
array($id=>$name);
And your searches can be like:
array_search($name,$arr);
This will work very well as native method of finding a needle in a haystack will have a better implementation than your own implementation.
e.g.
$id = 2;
$name= 'Sunny';
$arr = array($id=>$name);
echo array_search($name,$arr);
Echoes 2
The major advantage in this method would be code readability.
If you know that you are going to need to perform many of these types of search within the same request then you can create an index array from them. This will loop through the array once per index you need to create.
$piName = array();
foreach ($p as $k=>$v)
{
$piName[$v['Name']] = $k;
}
If you only need to perform one or two searches per page then consider moving the array into an external database, and creating the index there.
$index = 0;
$search_for = 'John';
$result = array_reduce($p, function($r, $v) use (&$index, $search_for) {
if($v['Name'] == $search_for) {
$r[] = $index;
}
++$index;
return $r;
});
$result will contain all the indices of elements in $p where the element with key Name had the value John. (This of course only works for an array that is indexed numerically beginning with 0 and has no “holes” in the index.)
Edit: Possibly even easier to just use array_filter, but that will not return the indices only, but all array element where Name equals John – but indices will be preserved:
$result2 = array_filter($p, function($elem) {
return $elem["Name"] == "John" ? true : false;
});
var_dump($result2);
What suits your needs better, resp. which one is maybe faster, is for you to figure out.

Categories