简体   繁体   English

PHP循环生成产生“重复项”

[英]PHP round robin generation creates 'duplicates'

I have implemented a round robin generator in PHP to create fixtures between users in a league. 我已经在PHP中实现了循环生成器,以在联盟中的用户之间创建固定装置。 This matches all the users in a league and pits them against each other for each gameweek. 这会匹配联盟中的所有用户,并使他们在每个游戏周内相互竞争。

The code looks like this; 代码看起来像这样;

    /**
     * Rotates an array for the round robin algorithm
     */
    function round_robin_array($array)
    {
        // we always keep index 0
        $top = array_shift($array);
        $last = array_pop($array);
        $rotate = [$last];
        foreach ($array as $_value) {
            $rotate[] = $_value;
        }
        array_unshift($rotate, $top);
        return $rotate;
    }

    /**
     * Runs a round robin to make a schedule.
     */
    function round_robin($users, $weeks)
    {
        $schedule = [];
        $count = count($users);
        foreach ($users as $_u) {
            $schedule[$_u] = array_fill(0, $weeks, []);
        }
        for ($i=0;$i<$weeks;$i++) {
            for ($a=0;$a<($count / 2) + 1;$a++) {
                $vs = $users[$a];
                $opp = $users[($count - $a) - 1];
                $at = rand(0,4);
                $pg = [$opp, $at];
                $og = [$vs, $at];
                $schedule[$vs][$i] = $pg;
                $schedule[$opp][$i] = $og;
            }
            $users = $this->round_robin_array($users);
        }
        return $schedule;
    }

    public function generateFixtures($league, $users, $weeks)
    {
        $array = [];

        foreach($users as $user) {
            array_push($array, $user['id']);
        }

        if(count($array) % 2 != 0) {
            array_push($array, '0');
        }

        $fixtures = $this->round_robin($array, $weeks);

        $gameweek = 1;

        foreach($fixtures as $key => $val) {
            if($key != 0) {
                foreach($val as $opponent) {
                    LeagueFixture::firstOrCreate([
                        'gameweek' => $gameweek,
                        'league_id' => $league,
                        'user_id' => $key,
                        'opponent_id' => $opponent[0],
                    ]);
                    $gameweek = $gameweek+1;
                }
            }
            $gameweek = 1;
        }

        return $fixtures;

    }

The generateFixtures function is passed the users of the league, the league itself and the number of weeks. generateFixtures函数将传递给联盟的用户,联盟本身以及周数。

The problem is this creates 'duplicates' for each fixture as there is essentially a view from each user - for example; 问题在于这会为每个灯具创建“重复项”,因为实际上每个用户都有一个视图,例如;

Gameweek 1 游戏周1

  • User_1 VS User_2 用户_1 VS用户_2
  • User_3 VS User_4 User_3 VS User_4
  • User_2 VS User_1 用户_2 VS用户_1
  • User_4 VS User_3 User_4 VS User_3

As you can see, the last two fixtures there are different; 如您所见,最后两个固定装置有所不同。 but the same! 但是一样!

My question is whether this is a problem with the round robin or whether i could/should filter out these duplicates when pulling them through in the controller/view 我的问题是循环是否有问题,或者在控制器/视图中将它们复制通过时是否可以/应该过滤掉这些重复项

It's not the most elegant solution, but at the point of data-entry to the database, i can check if the opposite of what is about to be created already exists; 这不是最优雅的解决方案,但是在向数据库输入数据时,我可以检查是否已经存在与要创建的对象相反的东西;

            foreach($fixtures as $key => $val) {
                if($key != 0) {
                    //loop through the values to create an entry for each
                    foreach($val as $opponent) {
                        //check if the opposite of each entry already exists
                        if(!LeagueFixture::where('gameweek', $gameweek)
                            ->where('league_id', $league)
                            ->where('user_id', $opponent[0])
                            ->where('opponent_id', $key)
                            ->exists()) {
                            //if not, we can create the entry as usual
                            LeagueFixture::firstOrCreate([
                                'gameweek' => $gameweek,
                                'league_id' => $league,
                                'user_id' => $key,
                                'opponent_id' => $opponent[0],
                            ]);
                        }
                        $gameweek = $gameweek+1;
                    }
                }
                $gameweek = 1;
            }

This is the easiest solution for me now.. although the data is generated in the above round robin (and you could easily argue this would be bad practice), the duplicate data never makes it into my database 这是现在对我来说最简单的解决方案。.尽管数据是在上述循环中生成的(并且您很容易会说这是不好的做法),但是重复的数据永远不会进入我的数据库

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM