Вычисление среднего значения из нескольких массивов за один цикл

php #arrays #loops #foreach

#php #массивы #циклы #foreach

Вопрос:

У меня есть некоторый код, который удаляет параметры из каждого URL-адреса из массива. Затем он суммирует оценки для каждого совпадающего URL-ключевого слова и, наконец, он должен получить среднее значение из одного из значений ‘position’.

У меня все работает. Но я думаю, есть ли какой-нибудь способ сделать это с помощью одного цикла? Теперь я использую для этого два цикла. Один из них суммирует значения для меня. Затем мне нужно использовать foreach и разделить сумму моих значений на количество совпадающих ключевых слов-url.

Может быть, у кого-нибудь есть идея, как я могу вычислить среднюю оценку «позиции» за один цикл?

  <?php

           $keywordsUrlsArray = array(
            0 => array
            (
                'url' => 'https://www.example.pl/?test=19',
                'keyword' => 'test',
                'score1' => 100,
                'score2' => 50,
                'position' => 4
            ),

            1 => array
            (
                'url' => 'https://www.example.pl/?test=2',
                'keyword' => 'test',
                'score1' => 100,
                'score2' => 50,
                'position' => 1
            ),

            2 => array
            (
                'url' => 'https://www.example.pl/?test=3',
                'keyword' => 'test',
                'score1' => 100,
                'score2' => 50,
                'position' => 3
            ),
            3 => array
            (
                'url' => 'https://www.example.pl/other-site?test=3',
                'keyword' => 'test',
                'score1' => 100,
                'score2' => 50,
                'position' => 3
            )
        );
 

И для этого есть код.

 $res = array();
            foreach ($keywordsUrlsArray as $urlResults) {
                //remove params from url
                $parsedUrl = parse_url($urlResults['url']);
                $parsedUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . $parsedUrl['path'];
                $keyword = $urlResults['keyword'];
    
                if (array_key_exists($parsedUrl, $res)) {
                    //check if parsed url with removed parameters exists and if it has the same keyword I need to sum scores 
                    if (isset($res[$parsedUrl][$keyword])) {
                        $res[$parsedUrl][$keyword]['urlCount']  = 1;
                        $res[$parsedUrl][$keyword]['score1']  = $urlResults['score1'];
                        $res[$parsedUrl][$keyword]['score2']  = $urlResults['score2'];
                        $res[$parsedUrl][$keyword]['position']  = $urlResults['position'];//my problem is there any way to compute my average position wtihout do a second foreach below?
                        continue;
                    }
                }
                $res[$parsedUrl][$keyword] = $urlResults;
                $res[$parsedUrl][$keyword]['url'] = $parsedUrl;
                $res[$parsedUrl][$keyword]['urlCount'] = 1;
            }
    
            //there I have to do a second foreach to compute average keyword/url position
            //and compute position which will be sum of all positions divided by every matched keyword/url
            $result = [];
            foreach ($res as $k => $r) {
                foreach ($r as $p => $t) {
                    $t['position'] = $t['position'] / $t['urlCount'];
                    unset($t['urlCount']);
                    $result[] = $t;
                }
            }
            var_dump( $result);
            return $result;
}
 

И вот мой результат. Сумма позиций, разделенных на встречающиеся URL-адреса.

 array(2) {
  [0]=>
  array(5) {
    ["url"]=>
    string(23) "https://www.example.pl/"
    ["keyword"]=>
    string(4) "test"
    ["score1"]=>
    int(300)
    ["score2"]=>
    int(150)
    ["position"]=>
    float(2.6666666666667)
  }
  [1]=>
  array(5) {
    ["url"]=>
    string(33) "https://www.example.pl/other-site"
    ["keyword"]=>
    string(4) "test"
    ["score1"]=>
    int(100)
    ["score2"]=>
    int(50)
    ["position"]=>
    int(3)
  }
}
        
 

Ответ №1:

Вы можете отслеживать сумму позиций и обновлять позицию каждый раз, когда у вас есть совпадение с URL.

В конце вашего кода инициализируйте первую сумму, чтобы не пропустить первое совпадение.

 foreach ($keywordsUrlsArray as $urlResults) {
    $parsedUrl = parse_url($urlResults['url']);
    $parsedUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . $parsedUrl['path'];
    $keyword = $urlResults['keyword'];

    if (array_key_exists($parsedUrl, $res)) {
        if (isset($res[$parsedUrl][$keyword])) {
            $res[$parsedUrl][$keyword]['urlCount']  = 1;
            $res[$parsedUrl][$keyword]['score1']  = $urlResults['score1'];
            $res[$parsedUrl][$keyword]['score2']  = $urlResults['score2'];            
            $res[$parsedUrl][$keyword]['sumPosition']  = $urlResults['position'];
            $res[$parsedUrl][$keyword]['position'] = $res[$parsedUrl][$keyword]['sumPosition'] / $res[$parsedUrl][$keyword]['urlCount'];
            continue;
        }
    }
    $res[$parsedUrl][$keyword] = $urlResults;
    $res[$parsedUrl][$keyword]['url'] = $parsedUrl;
    $res[$parsedUrl][$keyword]['urlCount'] = 1;
    $res[$parsedUrl][$keyword]['sumPosition'] = $urlResults['position'];
}
 

Это даст вам позицию в том же цикле, но у вас все равно будут ключи urlCount и sumPosition в конечных массивах.

Смотрите демонстрацию php.