简体   繁体   中英

How to rebuild an array with no repeats & other limits?

I have an app that allows people to serve custom assessments. I've built a new scoring mechanism at a client's request that allows the participant to select between two questions according to which is more accurate for them. The problem is that I need to randomize the questions, insure that two questions from the same category do not appear together, & limit it so two questions from the same two categories are only compared three times.

I've tried to adapt code/answers from other questions here, but none of them directly apply and I'm having difficulty adapting the ones that are the closest.

Here is a sample from my original array containing the questions (already randomized, but without the other criteria)...

Array
(
    [0] => Array
        (
            [question_id] => 2087
            [category_id] => 287
            [question] => Question would appear here
        )

    [1] => Array
        (
            [question_id] => 2068
            [category_id] => 286
            [question] => Question would appear here
        )

    [2] => Array
        (
            [question_id] => 2067
            [category_id] => 286
            [question] => Question would appear here
        )

    [3] => Array
        (
            [question_id] => 2073
            [category_id] => 286
            [question] => Question would appear here
        )

    [4] => Array
            [question_id] => 2029
            [category_id] => 283
            [question] => Question would appear here
        )

    [5] => Array
        (
            [question_id] => 2083
            [category_id] => 287
            [question] => Question would appear here
        )

    [6] => Array
        (
            [question_id] => 2084
            [category_id] => 287
            [question] => Question would appear here
        )

    [7] => Array
        (
            [question_id] => 2036
            [category_id] => 283
            [question] => Question would appear here
        )

    [8] => Array
        (
            [question_id] => 2062
            [category_id] => 285
            [question] => Question would appear here
        )

    [9] => Array
        (
            [question_id] => 2045
            [category_id] => 284
            [question] => Question would appear here
        )

    [10] => Array
        (
            [question_id] => 2052
            [category_id] => 285
            [question] => Question would appear here
        )
)

There are 30 questions total. To insure there is an even distribution, questions from the two categories should only be compared three times.

How do I build a new array from this one using PHP that...?

  1. Randomizes the questions
  2. Pairs questions between different categories
  3. Insures categories are only compared three times

--UPDATE-- Adding MySQL table structure in case it's easier to build an advanced query to do what I'm looking for...

CREATE TABLE `questions` (
  `question_id` int(5) unsigned NOT NULL AUTO_INCREMENT,
  `category_id` int(5) unsigned NOT NULL,
  `question` text NOT NULL,
  PRIMARY KEY (`question_id`),
  UNIQUE KEY `question_id` (`question_id`),
  KEY `questions_ibfk_1` (`category_id`),
  CONSTRAINT `questions_ibfk_1` FOREIGN KEY (`category_id`) REFERENCES `categories` (`category_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

CREATE TABLE `categories` (
  `category_id` int(5) unsigned NOT NULL AUTO_INCREMENT,
  `category` varchar(64) NOT NULL,
  PRIMARY KEY (`category_id`),
  UNIQUE KEY `category_id` (`category_id`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

--UPDATE--

I'm posting this as a MySQL question as I believe building the right query will suffice for what I'm needing. If you have an idea on how to do so, please post to the following question...

How do I build a MySQL query that pulls distinct pairs with a limit on how many times categories can match?

If you know a way to accomplish this via arrays, would still love to know how to do so. Thanks!

Here is what I finally came up with that worked (after attempting unsuccessfully to build the query I needed to accomplish the same thing)...

The original array $theresults contains all 60 questions from the 5 different categories. I begin by building an array of all the question categories...

// Create array of all categories
$allcategories = array();
$this->db->select('category_id');
$this->db->where('template_id',$template_id);
$query_thecategories = $this->db->get('categories');
$number_thecategories = $query_thecategories->num_rows();
if ($number_thecategories>0) {
    foreach ($query_thecategories->result() as $row_thecategory) {
        $thecategory = 'cat_' . $row_thecategory->category_id;
        $$thecategory = '0';
        $allcategories[] = $row_thecategory->category_id;
    }
}

Then I use the following function to pull all the unique combinations of categories...

function array_search_by_key($array, $key, $value) {
    if(!is_array($array)) {
        return [];
    }
    $results = [];
    foreach($array as $element) {
        if(isset($element[$key]) && $element[$key] == $value) {
            $results[] = $element;
        }
    }
    return $results;
}

$uniquecombos = uniquecombos($allcategories, 2);

Lastly, I loop through each of the combos to pull questions that match each category in the pair and store the result in a new array. (I loop it three times because each category pairing will be used three times (10 combinations of question pairs x 3 loops = 60 questions.) I also remove each question I pull from the original $theresults array to insure there are no duplicates...

// Create an empty array to capture the paired questions
$pairs = array();

// Loop through unique combos array 3 times to build pairings
for($combos = 1; $combos <= 3; $combos++) {
    foreach ($uniquecombos as $theset) {
        // Get two categories in pair
        $firstcategory = $theset[0];
        $secondcategory = $theset[1];

        // Gather other arrays which matches each category
        $matchesfirst = array_search_by_key($theresults,'category_id',$firstcategory);
        shuffle($matchesfirst);
        $matchessecond = array_search_by_key($theresults,'category_id',$secondcategory);
        shuffle($matchessecond);

        // Get question from each new array & add; remove selected question from the original array
        $pairs[] = $matchesfirst[0];
        unset($theresults[$matchesfirst[0]['question_id']]);
        $pairs[] = $matchessecond[0];
        unset($theresults[$matchessecond[0]['question_id']]);
    }
}

Hopefully this helps someone else!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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