我试图获取一个Ruby Array of Arrays并对其进行分组以计算其值。
数组有一个月,一个布尔值:
array = [["June", false], ["June", false], ["June", false], ["October", false]]
我想以一个新数组结束,让我知道每个月有多少虚假与真实。
示例:(数组中的第一项是月份,第二项是假数,第三项是真数)
new_array = [["June", 3, 0]], ["October", 1, 0]]
答案 0 :(得分:3)
Array.group_by { |month, b| month }.map{ |month, xs|
[month,
xs.count {|_, b| !b}, # false
xs.count {|_, b| b}] # true
}
# => [["June", 3, 0], ["October", 1, 0]]
答案 1 :(得分:1)
array.map(&:dup) # we’ll mutate it
.group_by(&:shift)
.flat_map { |k, v| [k, v.partition { |e| e }.map(&:count)] }
#⇒ [ ['June', [0, 3] ], ['October', [0, 1] ] ]
答案 2 :(得分:0)
我认为这会为reduce
操作提供一个很好的用例。你可以这样做:
arr = [["June", false], ["June", false], ["June", false], ["October", false]]
logical_group = Hash.new{|h, k| h[k] = Hash.new(0) }
arr.reduce(logical_group) do |red, ele|
red[ele.first][:false_count] += 1 unless ele.last
red[ele.first][:true_count] += 1 if ele.last
red
end.reduce([]) do |red, (key, value)|
red << [key, value[:false_count], value[:true_count]]
red
end
答案 3 :(得分:0)
Enumerable#group_by
是一个有用的工具,但在这种情况下,它并不是最好的工具。
如果我们从默认值为[0, 0]
的Hash开始,我们可以(几乎)做所有事情 - 查看月份(或获取默认值为新月份)并将1添加到适当的索引( 0
为false,1
为true) - 只需一步:
array = [["June", false], ["June", false], ["June", false], ["October", false]]
hsh = Hash.new {|h,k| h[k] = [0,0] }
array.each {|mo, bool| hsh[mo][bool ? 1 : 0] += 1 }
p hsh.map(&:flatten)
# => [["June", 3, 0], ["October", 1, 0]]
答案 4 :(得分:-2)
$films = Film::with('genre')->with('languages')->with('likes')->with('comments')->with('likedBy');
if(Input::get('sort')){
$sort = Input::get('sort');
switch ($sort){
case 'old_new':
$films = $films->orderBy('created_at', 'asc');
break;
case 'new_old':
$films = $films->orderBy('created_at', 'desc');
break;
case 'views':
// $films = DB::table('films')
// ->leftJoin('film_views', 'films.id', '=', 'film_views.film_id')
// ->select(DB::raw('films.*, count(film_views.film_id) as views'))
// ->groupBy('films.id')
// ->orderBy('views' , 'desc')
// ;
$films = $films
->leftJoin('film_views', 'films.id', '=', 'film_views.film_id')
->select(DB::raw('films.*, count(film_views.film_id) as views'))
//->whereBetween('created_at', [$this->first_day_of_search, $this->final_day_of_search])
->groupBy('films.id')
->orderBy('views' , 'desc')
;
break;
case 'likes':
$films = $films
->leftJoin('film_likes', 'films.id', '=', 'film_likes.film_id')
->select(DB::raw('films.*, count(film_likes.film_id) as likes'))
->groupBy('films.id')
->orderBy('likes' , 'desc')
;
break;
}
}
if(Input::get('filter')) {
$jsonFilter = Input::get('filter');
$filters = json_decode($jsonFilter);
foreach ($filters as $filter => $value){
switch ($filter){
case "genre":
if($value){
$films = $films->whereHas('genre', function ($query) use($value) {
$query->whereIn('genre_id', $value);
});
}
break;
case "cert":
if($value){
$films = $films->whereIn('cert', $value);
}
break;
case "country":
if($value){
$films = $films->whereIn('country', $value);
}
break;
case "lang":
if($value){
$films = $films->whereHas('languages', function ($query) use($value) {
$query->whereIn('language_id', $value);
});
}
break;
}
}
}
$films = $films->paginate(5);
return parent::api_response($films->toArray(), true, ['return' => 'all films'], 200);