Count Array values php - php

I am using laravel, I am getting this error when trying to count the valuse of this array.
Error:array_count_values(): Can only count STRING and INTEGER values!
the function:
public function test()
{
$test = \DB::table('surveys')->where('company_id', '=', 1)->select('rd1')->get()->toArray();;
$c = array_count_values($test);
$val = array_search(max($c), $c);
return view ('companies.test', compact('val'));
}
here is a var_dump of $test:
array:4 [▼
0 => {#204 ▼
+"rd1": "option1"
}
1 => {#206 ▼
+"rd1": "option1"
}
2 => {#207 ▼
+"rd1": "option1"
}
3 => {#208 ▼
+"rd1": "option1"
}
]

Your array is 2d which array_count_values doesn't like. You can either perform a loop and count the values yourself, or use something like array_column to get an array of the value from just the one column. Example:
array_count_values(array_column($test, $columnName))
array_column will get an array of values from just the one column you specify, which in your case is a string and that returned array can be passed to array_count_values to get the result you want.
Of course though, as someone else commented, this grouping and counting can be done by the database much more efficiently (you would be passing back less data and the database can be optimized to return queries like this with indexes). Here is another question that covers this.
You could then turn that back into a similar array with just array_column like:
\DB::table('surveys')
->where('company_id', '=', 1)
->select('rd1', \DB::raw('count(*) as total')
->groupBy('rd1')
->get()
->toArray();;
array_column($test, 'total', 'rd1');

The built-in function array_count_values() can't calculate the
frequency if the elements are not strings or numbers. You can, however,
easily perform a loop to do so:
foreach ($array as $e)
$frequency[$e] =+ 1;
This would basically do the same as the built-in. Note that the elements
are used as keys for the final frequency array (and you can imagina that
if $e is not a valid key (string or number) it will fail). In your
case, you need to use as key a property of your element. For example, if
it is another array:
foreach ($test as $e)
$frequency[$e['survey_name']] += 1;
Or properties/methods of an object:
foreach ($test as $e)
$frequency[$e->myColumn()] += 1;

Related

Restructure 2d array so that column values become row values (transpose but preserve first level keys)

The situation is as follows. I have a parent array which looks like the following:
$parent = [
1 => ['test1', 'test2'],
2 => ['test1_1', 'test2_2'],
];
I would like to group the data by column.
Desired result:
[
1 => ['test1', 'test1_1'],
2 => ['test2', 'test2_2'],
]
1 parent array called parent contains 2 arrays inside. I want to combine these two so that they have the same values as stated above. So this would mean that the arrays should be combined based on index number.
Since I do not make use of string keys, how would I accomplish this? I believe that there is no build in function available for this situation.
I would imagine that I could start beginning to create a new array and use a for loop through the parent array.
I tried the array-combine function however, this is NOT displaying the results I want.
[
1 => ['test1' => 'test1_1', 'test2' => 'test2_2'
]
If you need to preserve those first level keys, you can re-apply them after tranposing.
Code: (Demo)
var_export(
array_combine(array_keys($parent), array_map(null, ...$parent))
);
Otherwise, you can just transpose and accept the re-indexed first level keys. Honestly, I can't see any good reason to preserve the first level keys because by transposing, you remove the initial association between first level keys and the row values.
Code: (Demo)
var_export(
array_map(null, ...$parent)
);
If these techniques do not suit your actual project data, then we will need a more realistic sample array to be provided in your question body.
Loop over the keys of the top-level array. Then use the current index of the iteration to get the corresponding columns of the nested arrays.
$result = [];
foreach (array_keys($parent) as $i => $k) {
$result[$k] = array_column($parent, $i);
}
DEMO
This assumes the number of rows is the same as the number of columns. It's not clear what you expect the result to be if that's not true.

Laravel make array and use strtolower

I have data like this:
array:1 [
0 => "No Brand,ddfg"
]
First of all this data is wrong, what I want is to have something like this:
array:2 [
0 => "No Brand"
1 => "ddfg"
]
So now its really an array :)
Then I need my array data transform to lower case like:
array:2 [
0 => "no brand"
1 => "ddfg"
]
Code
$sibarBrandsArray = SidebarManager::first()->pluck('brands')->toArray();
This return data like:
array:1 [
0 => "No Brand,ddfg"
]
And this is how my data looks like in database:
Any idea?
Solved
// get my table row
$sibarBrandsArray = SidebarManager::first();
// get my row column
$getBrandColumn = $sibarBrandsArray->brands;
// separate data in that column with comma
$separateBrands = explode(',', $getBrandColumn);
// lowercase each separated data
$brandsArray = array_map('strtolower', $separateBrands);
// dump the result
dd($brandsArray);
Result
array:2 [
0 => "no brand"
1 => "ddfg"
]
Laravel has a very efficient and easy way to work with arrays. It's called a collection. Click here to learn more. Don't convert your response to the array, use collection directly.
$sibarBrandsCollection = SidebarManager::first()->pluck('brands');
Laravel eloquent by default gives you collection instance when you get a response. so pluck in above call is nothing but calling pluck on collection instance. We can chain method to the collection and do manipulation as needed.
$sibarBrandsCollection = $sibarBrandsCollection->map(function ($name) {
return strtolower($name);
});
Above code will automatically convert all of your values to lowercase. Similarly, you can explode the value to get your intended result. At last, if you have to send data as array to the browser just add toArray() method at the end of your collection.
I would not use core PHP array function unless needed, Laravel collection is great way to work with arrays.
$yourArray = array_map('strtolower', $yourArray);
$yourArray = array_map('nestedLowercase', $yourArray);
function nestedLowercase($value) {
if (is_array($value)) {
return array_map('nestedLowercase', $value);
}
return strtolower($value);
}
or you can use:
$query->whereRaw('LOWER(`newsTitle`) LIKE ? ',[trim(strtolower($newsTitle)).'%']);

Merging objects in PHP based on a property [duplicate]

This question already has answers here:
Merging and group two arrays containing objects based on one identifying column value
(4 answers)
Closed last month.
What I am originally trying to do is merge two objects
I have one object like this
{#23 ▼
+"Name": "Consultation"
+"ServiceId": "1024"
+"Price": ".00"
}
Another object
{#362 ▼
+"StartTime": "9:15AM"
+"ServiceId": "1024"
}
I am looking for a way to merge these two objects based on it's ServiceId, so I get a single object like this
{#1 ▼
+"Name": "Consultation"
+"ServiceId": "1024"
+"Price": ".00"
+"StartTime": "9:15AM"
}
Of course, if the ServiceId between the two objects do not match, it should not merge.
Any ideas on how to solve the error?
There seems to be two parts to your question. The first part is how to merge the output of two objects returned by json_decode. The second part is how to merge them only if the ServiceId match.
Part 1
json_decode produces, by default, objects of class \StdClass. If you want merge two \StdClass objects into a third \StdClass object, you need some judicious casting:
$a = json_decode('{"Name":"Consultation", "ServiceId":"1024", "Price":".00"}');
$b = json_decode('{"StartTime": "9:15AM", "ServiceId": "1024"}');
$c = (object)array_merge((array)$a, (array)$b);
var_dump($c);
Here, $a and $b are \StdClass objects. Cast them to array, merge, then cast them back to \StdClass.
That's a bit of a round-about way to go. So, you can benefit from working with these as arrays from the get-go. json_decode takes an optional second argument, which instructs it to return an array:
$a = json_decode('{"Name":"Consultation", "ServiceId":"1024", "Price":".00"}', true);
$b = json_decode('{"StartTime": "9:15AM", "ServiceId": "1024"}', true);
$c = array_merge($a, $b);
var_dump($c);
This works in arrays the whole time. If you later want $c to be a \StdClass object, you can cast it using $c = (object)$c; as was done in the first example.
See these live on 3v4l.org.
Part 2
Presumably, you're going to need some logic that iterates or otherwise pairs these objects together. You don't mention the source, but the logic will look something like this:
if ($a->ServiceId == $b->ServiceId) {
$c = (object)array_merge((array)$a, (array)$b)
}
If you have a list of objects, and you want to merge them all together, you can use the combinatoric array walk behavior of usort:
$merged = [];
usort($objects, function ($a, $b) use ($merged) {
$comp = strcmp($a->ServiceId, $b->ServiceId);
if (0 === $comp) {
$merged[] = (object)array_merge((array)$a, (array)$b)
}
return $comp;
});
var_dump($merged);
This iterates through your list of objects, comparing each. If the ServiceId match, then it merges the two objects and adds it to a list of merged. This will happen for as many objects that share ServiceId as you have in your list.
The idea here is too loop through 1 array and find the (assuming 1) element in the other array that match the current one:
foreach ($array1 as $key => $item) {
$other = array_filter($array2, function ($item2) use ($item) {
return $item2->ServiceId == $item->ServiceId;
});
if (!empty($other)) {
$item->StartTime = current($other)->SomethingElse;
}
}
Because you're dealing with objects merging all properties is a bit tricky.
Here's an example:
http://sandbox.onlinephpfunctions.com/code/15a9710dea77672c4ac4165044ad2c7aae4ae234

How to filter the Unique Objects in this PHP array object [duplicate]

This question already has answers here:
Filter/Remove rows where column value is found more than once in a multidimensional array
(4 answers)
Closed 9 months ago.
I have an array of objects generated from server side which I want to filter for duplicates in PHP ...
Below is the generated array
array:5 [▼
0 => {#204 ▼
+"category_name": "Fashion"
+"category_id": "fashion"
}
1 => {#205 ▼
+"category_name": "Fashion"
+"category_id": "fashion"
}
2 => {#209 ▼
+"category_name": "Shirts"
+"category_id": "shirts"
}
3 => {#210 ▼
+"category_name": "Health"
+"category_id": "health"
}
4 => {#211 ▼
+"category_name": "Shirts"
+"category_id": "shirts"
}
]
Here Array 0 and 1, Array 2 and Array 4 have same values, how to filter and get only a single values for the duplicate in the existing array or a newly generated array.
By looking at your data, it appears that you could filter through your array of objects by comparing the uniqueness of ONE property. If that's the case, when dealing with very large arrays, it's much more efficient to compare a single property instead of essentially turning each object into a string and doing a comparison that way.
Here's a function that should return objects that are unique by one property:
function returnUniqueProperty($array,$property) {
$tempArray = array_unique(array_column($array, $property));
$moreUniqueArray = array_values(array_intersect_key($array, $tempArray));
return $moreUniqueArray;
}
$uniqueObjectsById = returnUniqueProperty($yourArray, 'category_id');
Explanation:
We pass in to our function, the array, and the property name of column you want to perform the "uniqueness" comparison with.
Then we use php's array_column() function to return an array of only the property we want to compare. This array will have the same index values as our original array. php.net
Then we use array_unique() to filter out any duplicates in our temporary array. Crucially, by default, this will remove duplicates, but preserve the original index positions of each unique property value. php.net
Now, we just have to match the index positions of our unique array of property values with our original array's index values, with array_intersect_key(). php.net
Finally, we want to "compact" our array, so we array_values(), which returns a new array with a fresh index in numerical order. php.net
Use array_unique() PHP function:
http://php.net/manual/en/function.array-unique.php
I have the same problem. After adding SORT_REGULAR in array_unique then it works for me.
array_unique($objectArray, SORT_REGULAR)
//comment start:: Dont change "returnUniqueProperty" function
function returnUniqueProperty($array,$property) {
$tempArray = array_unique(array_column($array, $property));
$moreUniqueArray = array_values(array_intersect_key($array, $tempArray));
return $moreUniqueArray;
}
//comment end::
$uniqueObjectsById = returnUniqueProperty($yourArray, 'category_id');
// "yourArray" replace with your arrayname
//"category_id" is property to filter:: in your case "category_id"

Array keys by another arrays values

I have an array $params with the following content:
Array(
0 => "array"
1 => "arrayName" //variable
2 => "key1" //optional&variable ie. 0 or 'foo'
3 => "key2" //optional&variable ie. 0 or 'foo'
//etc.
)
Also, I have an stdObject that contains all my variables for the page that is being requested (MVC style).
So, I could have an array in there like this:
$std = new stdObject();
$std->arrayName->array('foo', 'bar');
Now I want the first value of the $std array. So I am using the "key1" parameter in $params and set this to '0' so it will pick the $std->arrayName[0] value ('foo'). Note that I am not using the "key2" parameter since I don't want to select $std->arrayName[key1][key2].
But what if I need the value of a nested array?
$std = new stdObject();
$std->arrayName->array('foo', array('bar', 'fish'));
I will request the $std->arrayName[1][1] value ('fish') by setting the "key1" parameter to 1 and the "key2" parameter to 1 as well. So it will select $std->arrayName[key1][key2].
But what if I have 10 arrays nested in each other? highly unlikely, but it's possible. I want to select $std->arrayName[key1][key2][key3][..][key10] to select a certain value that's located there.
For example: $std->arrayName[0][3][4][6][2][9]['foo']['bar][9][2];
So my question is: how do I select the value of a certain array (arrayName) by the values defined in another array ($params) that act as the keys for the first array (arrayName). But, the amount of keys (values in $params) is optional.
Maybe the question isn't completely understandable, so feel free to ask more information.
You need to loop the key array and assign each level to a variable, until you reach the end when you should have the value you want.
Something like this (untested, no error checking):
function array_value_at ($array, $keys) {
foreach ($keys as $key) {
$array = $array[$key];
}
return $array;
}

Categories