How to Group by Count in Array Without Using Loop

How to group by count in array without using loop

x = arr.inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }

How to count groups of integers within arrays, without sorting the array?

First I would suggest to find all subgroups. For this you can use Stream.collect() with a custom collector:

List<List<Integer>> sublists = IntStream.of(1, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 4, 4, 4, 6)
.collect(ArrayList::new, (lists, value) -> {
if (lists.isEmpty() || lists.get(lists.size() - 1).stream().noneMatch(e -> e == value)) {
lists.add(new ArrayList<>());
}
lists.get(lists.size() - 1).add(value);
}, (l1, l2) -> {
throw new RuntimeException("not supported for parallel streams");
});

The result is:

[[1, 1, 1], [2], [1, 1], [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [4, 4, 4], [5], [4, 4, 4], [6]]

Now you can use this to group the list sizes:

Map<Integer, Long> result = sublists.stream()
.collect(Collectors.groupingBy(List::size, Collectors.counting()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));

This finds all existing group sizes and prints:

size 1 count 3
size 2 count 1
size 3 count 3
size 10 count 1

To count all groups with a min length you can use:

Map<Integer, Long> result = IntStream.rangeClosed(1, sublists.stream().mapToInt(List::size).max().orElse(0)).boxed()
.collect(Collectors.toMap(Function.identity(), i -> sublists.stream().filter(l -> l.size() >= i).count()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));

This prints:

size 1 count 8
size 2 count 5
size 3 count 4
size 4 count 1
size 5 count 1
size 6 count 1
size 7 count 1
size 8 count 1
size 9 count 1
size 10 count 1

To get only a predefined set of sizes (e. g. 1, 2, 6, 8) you can modify the last solution:

Map<Integer, Long> result = IntStream.of(1, 2, 6, 8).boxed()
.collect(Collectors.toMap(Function.identity(), i -> sublists.stream().filter(l -> l.size() >= i).count()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));

The result of this is:

size 1 count 8
size 2 count 5
size 6 count 1
size 8 count 1

Search group of numbers in int array without using a loop

Technically you can use recursion but that doesn't really gets rid of a loop. You just dont write the keyword while or for

public static void main(String[] args) {
int[] a = { 4, 5, 6, 5, 4, 3 };
System.out.println(sequenceRecursive(a, 0, 0, 0));
}

public static int sequenceRecursive(int[] arr, int startIndex, int longest, int sequence) {
if(startIndex <= 0) startIndex = 1;
if(startIndex >= arr.length) return longest + 1;
if(arr[startIndex] > arr[startIndex - 1]){
sequence++;
if(sequence > longest) longest = sequence;
}else{
sequence = 0;
}
return sequenceRecursive(arr, ++startIndex, longest, sequence);
}

Group array values using loop and count with Twig

Try something like this:

{% for key, i in data['pet_name'] %}
<ul>
<li>Pet Num: {{ key + 1}}</li>
<li>{{ data['pet_name'][key] }}</li>
<li>{{ data['type'][key] }}</li>
<li>{{ data['age'][key] }}</li>
<li>{{ data['gender'][key] }}</li>
</ul>
{% endfor %}

It should print:

<ul>
<li>Pet Num: 1</li>
<li>Bob</li>
<li>cat</li>
<li>1</li>
<li>female</li>
</ul>
<ul>
<li>Pet Num: 2</li>
<li>Buster</li>
<li>dog</li>
<li>22</li>
<li>male</li>
</ul>

Edit: It seems you have an object with arrays, in that case try something like this:

{% for key, i in data.pet_name %}
<ul>
<li>Pet # {{ key + 1}}</li>
<li>{{ data.pet_name[key] }}</li>
<li>{{ data.type[key] }}</li>
<li>{{ data.age[key] }}</li>
<li>{{ data.gender[key] }}</li>
</ul>
{% endfor %}

Good luck!

Group rows in a multidimensional array and sum the count elements in each group

I've done my best to make it less verbose. I welcome any suggestions. Here's my proposed solution:

function sumOccurrences(array $original): array
{
$summed = [];
foreach ($original as $value) {
// here we get the array without the 'count' key - everything we need to compare
$comparisonElement = array_filter($value, function ($key) {
return $key !== 'count';
}, ARRAY_FILTER_USE_KEY);
// we search with strict comparison (third param - true) - see reasoning below
$foundAt = array_search($comparisonElement, array_column($summed, 'element'), true);
if ($foundAt === false) {
// we separate the values we compare and the count for easier handling
$summed[] = ['element' => $comparisonElement, 'count' => $value['count']];
} else {
// if we've run into an existing element, just increase the count
$summed[$foundAt]['count'] += $value['count'];
}
}

// since we separated count from the values for comparison, we have to merge them now
return array_map(function ($a) {
// $a['count'] is wrapped in an array as it's just an integer
return array_merge($a['element'], ['count' => $a['count']]);
}, $summed);
}

In order to make it less verbose, I've opted to compare arrays directly. Other than being less verbose, another benefit is that this will work if additional key => value pairs are introduced to the array without any addition to logic. Everything that is not count gets compared, no matter how many pairs exist. It will also cover any nested arrays (for example 'C' => ['D' => 1]).

But, this comes at a price - we must use strict comparison because loose can give undesired results (for example, ['a'] == [0] will return true). Strict comparison also means that it won't work if any values are objects (strict comparison means it's checking for the same instance) and that arrays will only be matched if they have the same key => value pairs in the same order. This solution assumes that your array (and any nested ones) are already sorted.

If that is not the case, we'd have to sort it before comparing. Normally, ksort would do the job, but to support nested arrays, we'd have to devise a recursive sort by key:

function ksortRecursive(array &$array): void
{
ksort($array);
foreach ($array as &$value) {
if (is_array($value)) {
ksortRecursive($value);
}
}
}

and call it before we do array_search.

Now if we assume a starting array like in your example, the following should give you the desired result:

$original = [
['A' => 'O', 'B' => 'O', 'C' => 1, 'count' => 1],
['A' => 'Test', 'B' => 'Test', 'C' => 1, 'count' => 1],
['A' => 'O', 'B' => 'O', 'C' => 1, 'count' => 1],
['A' => 'Test', 'B' => 'Test', 'C' => 1, 'count' => 1],
['A' => 'Test', 'B' => 'test1', 'C' => 2, 'count' => 1],
];
var_dump(sumOccurrences($original));

How to count group of consecutive numbers in array

In the future, try to include more info on what you've tried or what you've researched. As Azro said, we're here to help, not complete tasks for you.

int[] myArr = {1,2,3,4,9,12,17,23,34,54,55,56};
int consecutiveSums = 0;

// Iterate through the array
for (int i = 0; i < myArr.length; i++) {
// Check if the next value is consecutive
if (i + 1 < myArr.length && myArr[i] + 1 == myArr[i+1]) {
consecutiveSums ++;
// Skip any remaining consecutives until we reach a new set
while (i + 1 < myArr.length && myArr[i] + 1 == myArr[i+1]) {
i++;
}
}
}

System.out.println(consecutiveSums);

Grouping and conditions without loop (big data)

My dataset had too many different groups, and the plyr option proposed by Troy was too slow.
I found a hack (experts would probably say "an ugly one") with package data.table : the idea is to merge the data.table with itself quickly with the fast merge function. It gives every possible combination between a given year of a group and all others years from the same group.
Then proceed with an ifelse for every row with the condition you're looking for.
Finally, aggregate everything with a sum function to know how many times every given years can be found in a given timespan relative to another year.
On my computer, it took few milliseconds, instead of the probable hours that plyr was going to take

dat = data.table(group = rep(c("a","b","c"),each = 3), year = c(2000, 1996, 1975, 2002, 2010, 1980, 1990,1986,1995), key = "group")

Produces this :

group   year
1 a 2000
2 a 1996
3 a 1975
4 b 2002
5 b 2010
6 b 1980
7 c 1990
8 c 1986
9 c 1995

Then :

z = merge(dat, dat, by = "group", all = T, allow.cartesian = T) # super fast

z$sixyears = ifelse(z$year.y >= z$year.x - 6 & z$year.y < z$year.x, 1, 0) # creates a 0/1 column for our condition
z$sixyears = as.numeric(z$sixyears) # we want to sum this up after
z$year.y = NULL # useless column now
z2 = z[ , list(sixyears = sum(sixyears)), by = list(group, year.x)]

(Years with another year of the same group in the last six years are given a "1" :

  group year x
1 a 1975 0
2 b 1980 0
3 c 1986 0
4 c 1990 1 # e.g. here there is another "c" which was in the timespan 1990 -6 ..
5 c 1995 1 # <== this one. This one too has another reference in the last 6 years, two rows above.
6 a 1996 0
7 a 2000 1
8 b 2002 0
9 b 2010 0

Icing on the cake : it deals with NA seamlessly.

Group by count of objects within an array in Vanilla Javascript

As others have mentioned, an object would be a better fit for aggregating the data. You could use a normal loop, or reduce to do it:

var data = [{person:101, year: 2012}, {person:102, year: 2012}, {person:103,year: 2013}];
var yearCounts = data.reduce(function (result, person) { var currentCount = result[person.year] || 0; result[person.year] = currentCount + 1; return result;}, {});
console.log(yearCounts);

How to count array with group by

You can loop over the array and count the instances of each city as you go.

$city_counts = array();                            // create an array to hold the counts
foreach ($array as $city_object) { // loop over the array of city objects
// checking isset will prevent undefined index notices
if (isset($city_counts[$city_object->city])) {
$city_counts[$city_object->city]++; // increment the count for the city
} else {
$city_counts[$city_object->city] = 1; // initialize the count for the city
}
}


Related Topics



Leave a reply



Submit