Ruby数组数组和按值计数

时间:2016-06-28 04:29:03

标签: arrays ruby

我试图获取一个Ruby Array of Arrays并对其进行分组以计算其值。

数组有一个月,一个布尔值:

array = [["June", false], ["June", false], ["June", false], ["October", false]]

我想以一个新数组结束,让我知道每个月有多少虚假与真实。

示例:(数组中的第一项是月份,第二项是假数,第三项是真数)

new_array = [["June", 3, 0]], ["October", 1, 0]]

5 个答案:

答案 0 :(得分:3)

使用Enumerable#group_by

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);