Count in Eloquent with distinct? - laravel

the following query:
Sheep::whereIn('foobar_id', [1, 2, 3, 4, 5])->groupBy('foobar_id')->count();
Also instead of using groupBy I tried distinct('foobar_id') with no effect.
How can I get a result of the counts where doubles of the foobar_id are skipped?
Using Postgres

Sheep::query()
->whereIn('foobar_id', [1, 2, 3, 4, 5])
->distinct()
->count('foobar_id');

Related

Writing a union operation in prolog for multisets

In the prolog there is a standard way to define union of two sets
But I want to write union function for multisets. That would mean if first set has [1,2] and
second has [2,3] then the output should be [1,2,2,3].
How do I go about writing such a function.
There is no type Set in Prolog. What you are referencing are just lists. The union predicate combines two lists with assumed unique elements to a new list where the elements are again unique. The order does not matter in a set. You see that when you pass a non-ordered/non-set list.
% both ordered, but result is not
?- union([1, 2, 5, 6], [3, 4, 7, 8], S).
S = [1, 2, 5, 6, 3, 4, 7, 8].
% sets, not ordered
?- union([1, 2, 3], [3, 2, 4, 5], S).
S = [1, 3, 2, 4, 5].
% multisets, not ordered
?- union([1, 2, 3], [3, 2, 4, 5, 5], S).
S = [1, 3, 2, 4, 5, 5].
To create a multiset, i.e. keep all elements in the set union, you can just combine the lists, while ordering them as you please. Formally, a multiset is not ordered as well, so if sorting does not matter, you can just append the second list to the first, which also works with your example:
?- append([1, 2, 4], [2, 3, 4, 5], S).
S = [1, 2, 4, 2, 3, 4, 5].
?- append([1, 2], [2, 3], S).
S = [1, 2, 2, 3].
If you can assume the lists to be ordered and you want that to be the case in the result, you can just merge them, which keeps the order:
?- merge([1, 2, 4], [2, 3, 4, 5], S).
S = [1, 2, 2, 3, 4, 4, 5].
If you can not assume the lists to be sorted, but you want to have the result sorted, you can also take care of the sorting yourself, e.g. with msort:
?- append([1, 2, 3], [3, 2, 4, 5, 5], S), msort(S, S1).
S = [1, 2, 3, 3, 2, 4, 5, 5],
S1 = [1, 2, 2, 3, 3, 4, 5, 5].
There are also more sorting predicates around, and if it's more complicated you can write one yourself, too.

Finding duplicate columns in a nested array

0 1 2 3 4 5 6
0{1,2,1,2,1,5,5}
1{5,4,5,4,5,1,1}
2{2,4,2,4,2,1,1}
3{1,2,1,2,1,1,1}
4{4,4,4,4,4,1,1}
5{2,4,2,4,2,2,2}
output: {{0,2,4}, {1,3}, {5,6}} (can use any data structure)
Let's say there is a nested array like above. If we wanted to find column indices that contain the same exact numbers in the same order (for example, column 0, 2, 4 with (1,5,2,1,4,2) and column 1, 3 with (2,4,4,2,4,4), and column 5, 6 with (5,1,1,1,1,2), how can we go about with this efficiently? Will it require dynamic programming?
Thanks in advance.
You can just iterate through the columns, keeping a hashmap of the columns that you've seen so far. Here's an implementation in python:
x = [[1, 2, 1, 2, 1, 5, 5],
[5, 4, 5, 4, 5, 1, 1],
[2, 4, 2, 4, 2, 1, 1],
[1, 2, 1, 2, 1, 1, 1],
[4, 4, 4, 4, 4, 1, 1],
[2, 4, 2, 4, 2, 2, 2]]
seen_before = {}
for v, col in enumerate(zip(*x)):
if tuple(col) not in seen_before:
seen_before[tuple(col)] = [v]
else:
seen_before[tuple(col)].append(v)
This solves the problem in linear time. I hope that's good enough for you.

Rails bug in Active Record Model

I was practicing my Code and soon I found that '.order' method works in reverse. My rails version is '5.0.0.1'
I used it like:
(i) User.order(salary: :desc).first(3)
(ii) User.order(salary: :desc).first(3)
I got reverse results. I am using mysql database. Can anybody tell me whether its mine mistake or really it's rails problem.
If you are trying to get ascending order result, you should be doing Ascending instead of Descending. The following code will sort the salary in ascending order and get the first 3.
User.order(salary: :asc).first(3)
The code that you provided below will sort the salary in descending order, and then select the first 3.
User.order(salary: :desc).first(3)
Example: given an array with unsorted value [3, 2, 4, 5, 1]. After the following code is executed, you will have the results as below
User.order(salary: :desc) >>> [5, 4, 3, 2, 1]
User.order(salary: :desc).first(3) >>> [5, 4, 3]
User.order(salary: :asc) >>> [1, 2, 3, 4, 5]
User.order(salary: :desc).first(3) >>> [1, 2, 3]

Sorting Array of Arrays having variable number of elements

I have to sort an array of arrays. I've searched for solutions however my problem is:
need to sort arrays that may have different sizes from a script run to another.
need to sort not only by one or two elements, but, if possible based in all elements.
For example, for the following inputs:
[[2,3,4,5,6],[1,3,4,5,7],[1,3,4,5,8]]
[[5,2,3],[2,2,4],[2,2,5]]
The output should be, respectively:
[[1,3,4,5,7],[1,3,4,5,8],[2,3,4,5,6]]
[[2,2,4],[2,2,5],[5,2,3]]
Do as below
input=[[2,3,4,5,6],[1,3,4,5,7],[1,3,4,5,8]]
input.sort # => [[1, 3, 4, 5, 7], [1, 3, 4, 5, 8], [2, 3, 4, 5, 6]]

"Pyramidizing" an array/list (in Ruby, but general solutions could probably be implemented)

I'm not sure what the best word to use here. By "pyramidizing", I mean:
[1,2,3,4].pyramidize # => [1,1,1,1,2,2,2,3,3,4]
["a","b","c","d"].pyramidize # => ["a","a","a","a","b","b","b","c","c","d"]
To represent visually, it could be thought of as:
[ 1,1,1,1,
2,2,2,
3,3,
4 ]
Is there a way to do this that maximizes elegance? A most ruby-like way?
I came across the "need" to do this in a project of mine. After thinking about it, I gave up and decided to work around the problem in an ugly way. I was wondering if there was a pretty way to do this. So far, to do it directly, I've ended up making a separate array for each index and stretching out each array the appropriate length and combining them together. But I don't know how to do this so it looks pretty; my solution is pretty ugly.
Added code golf tag because any solution in one line would probably make my day, but it doesn't have to be.
It doesn't really matter if your solution makes the first index the "base" of the pyramid, or the last index, because I could just reverse the array before running it.
Requires the new iterator fanciness in Ruby 1.9.
class Array
def pyramidize
reverse.map.with_index do |object, index|
[object] * (index + 1)
end.flatten.reverse
end
end
[1,2,3,4].pyramidize
=> [1, 1, 1, 1, 2, 2, 2, 3, 3, 4]
["a","b","c","d"].pyramidize
=> ["a", "a", "a", "a", "b", "b", "b", "c", "c", "d"]
irb(main):001:0> [2,1,3,5].flat_map.with_index{|i,j|[i]*(j+1)}
=> [2, 1, 1, 3, 3, 3, 5, 5, 5, 5]
irb(main):002:0> [1,2,3,4].flat_map{|i|[i]*i}
=> [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
I'm not sure if you want to use the value of the list or the index to determine how much the list should repeat, but a simple solution in python that can probably transfer to ruby easily:
>>> import operator
>>> input = range(6)
>>> reduce(operator.add, [[i]*idx for idx, i in enumerate(input)])
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5]
Update
Oh and to invert the counts:
>>> import operator
>>> input = range(1, 6)
>>> reduce(operator.add, [[i]*(max(input) - idx) for idx, i in enumerate(input)])
[1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5]
And of course you reversed the list in one of your examples:
>>> import operator
>>> input = range(1, 6)
>>> reduce(operator.add, [[i]*(max(input) - idx) for idx, i in enumerate(input)])[::-1]
[ 5,
4, 4,
3, 3, 3,
2, 2, 2, 2,
1, 1, 1, 1, 1]
FWIW, this is a mathy way of doing it:
>>> A = [1, 2, 3, 4]
>>> [ A[int((sqrt(8*k+1)-1) / 2)] for k in range(len(A)*(len(A)+1) / 2) ]
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
Admittedly, the use of sqrt is pretty ugly.
Here is another way to do it in Python
>>> A=[1,2,3,4]
>>> [y for i,x in enumerate(A) for y in [x]*(len(A)-i)]
[1, 1, 1, 1, 2, 2, 2, 3, 3, 4]
But it's nicer not to create all those temporary lists
>>> from itertools import repeat
>>> [y for i,x in enumerate(A) for y in repeat(x, len(A)-i)]
[1, 1, 1, 1, 2, 2, 2, 3, 3, 4]

Resources