Как array_merge динамический массив на основе одного из его значений сходства - PullRequest
0 голосов
/ 09 сентября 2010

Добрый день,

Я получаю информацию с разных сайтов, используя cURL и различные методы разбора. я сделал код, чтобы при желании я мог добавить дополнительные веб-сайты, с которых я сканировал информацию.

Полученная информация выглядит следующим образом: (Обратите внимание, что информация может быть неточной и может не отражать реальную цену / название)

Array
(
    [website1.com] => Array
        (
            [0] => Array
                (
                    [0] => 60" BRAVIA LX900 Series 3D HDTV
                    [1] => website1.com
                    [2] => 5299.99
                )
            [1] => Array
                (
                    [0] => 52" BRAVIA LX900 Series 3D HDTV
                    [1] => website1.com
                    [2] => 4499.99
                )
            [2] => Array
                (
                    [0] => 46" BRAVIA LX900 Series 3D HDTV
                    [1] => website1.com
                    [2] => 3699.99
                )
            [3] => Array
                (
                    [0] => 40" BRAVIA LX900 Series 3D HDTV
                    [1] => website1.com
                    [2] => 2999.99
                )
        )
    [website2.com] => Array
        (
            [0] => Array
                (
                    [0] => Sony 3D 60" LX900 HDTV BRAVIA
                    [1] => website2.com
                    [2] => 5400.99
                )
            [1] => Array
                (
                    [0] => Sony 3D 52" LX900 HDTV BRAVIA
                    [1] => website2.com
                    [2] => 4699.99
                )
            [2] => Array
                (
                    [0] => Sony 3D 46" LX900 HDTV BRAVIA
                    [1] => website2.com
                    [2] => 3899.99
                )
        )
)

Желаемый результат должен быть:

Array
(
    [0] => Array
        (
            [Name] => 60" BRAVIA LX900 Series 3D HDTV
            [website1.com] => 5299.99
            [website2.com] => 5400.99
        )
    [1] => Array
        (
            [Name] => 52" BRAVIA LX900 Series 3D HDTV
            [website1.com] => 4499.99
            [website2.com] => 4699.99
        )
    [2] => Array
        (
            [Name] => 46" BRAVIA LX900 Series 3D HDTV
            [website1.com] => 3699.99
            [website2.com] => 3899.99
        )
    [3] => Array
        (
            [Name] => 40" BRAVIA LX900 Series 3D HDTV
            [website1.com] => 2999.99
        )
)

Обратите внимание, что имя может отличаться, поэтому необходимо использовать Similar_text. Кроме того, некоторая информация может отображаться не на всех веб-сайтах. Я знаю, что нужно выбрать только одно телевизионное имя, тогда я буду использовать имя из наиболее подходящего источника (website1.com)

Вот коды, которые я пытаюсь заставить работать.

<?php
    $_Retreived = array(
        "website1.com" => array(
            array('60" BRAVIA LX900 Series 3D HDTV', 'website1.com', 5299.99),
            array('52" BRAVIA LX900 Series 3D HDTV', 'website1.com', 4499.99),
            array('46" BRAVIA LX900 Series 3D HDTV', 'website1.com', 3699.99),
            array('40" BRAVIA LX900 Series 3D HDTV', 'website1.com', 2999.99)
        ),
        "website2.com" => array(
            array('Sony 3D 60" LX900 HDTV BRAVIA', 'website2.com', 5400.99),
            array('Sony 3D 52" LX900 HDTV BRAVIA', 'website2.com', 4699.99),
            array('Sony 3D 46" LX900 HDTV BRAVIA', 'website2.com', 3899.99),
        )
    );

    $_Prices = array();
    $_PricesTemp = array();
    $_Sites = array("website1.com", "website2.com");

    for($i = 0; $i < sizeOf($_Sites); $i++)
    {
        $_PricesTemp = array_merge($_PricesTemp, $_Retreived[ $_Sites[$i] ]);
    }

    /*
        print_r($_PricesTemp);

        Array
        (
            [0] => Array
                (
                    [0] => 60" BRAVIA LX900 Series 3D HDTV
                    [1] => website1.com
                    [2] => 5299.99
                )
            [1] => Array
                (
                    [0] => 52" BRAVIA LX900 Series 3D HDTV
                    [1] => website1.com
                    [2] => 4499.99
                )
            [2] => Array
                (
                    [0] => 46" BRAVIA LX900 Series 3D HDTV
                    [1] => website1.com
                    [2] => 3699.99
                )
            [3] => Array
                (
                    [0] => 40" BRAVIA LX900 Series 3D HDTV
                    [1] => website1.com
                    [2] => 2999.99
                )
            [4] => Array
                (
                    [0] => Sony 3D 60" LX900 HDTV BRAVIA
                    [1] => website2.com
                    [2] => 5400.99
                )
            [5] => Array
                (
                    [0] => Sony 3D 52" LX900 HDTV BRAVIA
                    [1] => website2.com
                    [2] => 4699.99
                )
            [6] => Array
                (
                    [0] => Sony 3D 46" LX900 HDTV BRAVIA
                    [1] => website2.com
                    [2] => 3899.99
                )
        )
    */

    foreach($_PricesTemp As $_KeyOne => $_EntryOne)
    {
        foreach(array_reverse($_PricesTemp, true) As $_KeyTwo => $_EntryTwo)
        {
            if ($_KeyOne != $_KeyTwo)
            {
                $_Percent = 0;

                similar_text(strtoupper($_EntryOne[0]), strtoupper($_EntryTwo[0]), $_Percent);

                if ($_Percent >= 90) //If names matches 90%+
                {
                    echo "Similar : <b>" . $_KeyOne . "</b> " . $_EntryOne[0] . " and <b>" . $_KeyTwo . "</b> " . $_EntryTwo[0] . " Percent : " . $_Percent . "<br />";

                    $_Prices[] = array();
                    $_Prices[ sizeOf($_Prices)-1 ]['Name'] = $_EntryOne[0]; //Use the product name of the most revelant website (website1.com)

                    foreach($_Sites As $_Site)
                    {
                        if (isset($_EntryOne[ 1 ]) && $_EntryOne[ 1 ] == $_Site) //Check if it contains price from website1.com
                        {
                            $_Prices[ sizeOf($_Prices)-1 ][ $_Site ] = $_EntryOne[ 2 ];
                        }
                        if (isset($_EntryTwo[ 1 ]) && $_EntryTwo[ 1 ] == $_Site) //Check if it contains price from website2.com
                        {
                            $_Prices[ sizeOf($_Prices)-1 ][ $_Site ] = $_EntryTwo[ 2 ];
                        }
                    }
                }
            }
        }
    }

    /*
        print_r($_Prices);

        Array
        (
            [0] => Array
                (
                    [Name] => 60" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 2999.99
                )
            [1] => Array
                (
                    [Name] => 60" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 3699.99
                )
            [2] => Array
                (
                    [Name] => 60" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 4499.99
                )
            [3] => Array
                (
                    [Name] => 52" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 2999.99
                )
            [4] => Array
                (
                    [Name] => 52" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 3699.99
                )
            [5] => Array
                (
                    [Name] => 52" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 5299.99
                )
            [6] => Array
                (
                    [Name] => 46" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 2999.99
                )
            [7] => Array
                (
                    [Name] => 46" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 4499.99
                )
            [8] => Array
                (
                    [Name] => 46" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 5299.99
                )
            [9] => Array
                (
                    [Name] => 40" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 3699.99
                )
            [10] => Array
                (
                    [Name] => 40" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 4499.99
                )
            [11] => Array
                (
                    [Name] => 40" BRAVIA LX900 Series 3D HDTV
                    [website1.com] => 5299.99
                )
            [12] => Array
                (
                    [Name] => Sony 3D 60" LX900 HDTV BRAVIA
                    [website2.com] => 3899.99
                )
            [13] => Array
                (
                    [Name] => Sony 3D 60" LX900 HDTV BRAVIA
                    [website2.com] => 4699.99
                )
            [14] => Array
                (
                    [Name] => Sony 3D 52" LX900 HDTV BRAVIA
                    [website2.com] => 3899.99
                )
            [15] => Array
                (
                    [Name] => Sony 3D 52" LX900 HDTV BRAVIA
                    [website2.com] => 5400.99
                )
            [16] => Array
                (
                    [Name] => Sony 3D 46" LX900 HDTV BRAVIA
                    [website2.com] => 4699.99
                )
            [17] => Array
                (
                    [Name] => Sony 3D 46" LX900 HDTV BRAVIA
                    [website2.com] => 5400.99
                )
        )
    */
?>

Прежде всего, приведенный выше код не работает. Где-то должна быть логическая ошибка, которую я не могу понять. Кроме того, я не Поверьте, код будет работать, если я добавлю третий сайт в список.

Есть идеи, ребята? Я занимаюсь этим с утра.

Редактировать 2011-02-16:

Я добавил награду к этому вопросу.

Ответы [ 3 ]

1 голос
/ 19 февраля 2011

Попробуй суть яснее https://gist.github.com/835099

Это дало мне желаемый результат.

0 голосов
/ 21 февраля 2011

Проблема не может быть решена с использованием Similar_text.Вы хотите сопоставить 60" BRAVIA LX900 Series 3D HDTV с Sony 3D 60" LX900 HDTV BRAVIA.Тем не менее, 60" BRAVIA LX900 Series 3D HDTV на самом деле больше похож на 52" BRAVIA LX900 Series 3D HDTV, отличаются только два символа.

Я подозреваю, что вам понадобится специальный обработчик для сопоставления деталей, специфичных для продуктов, которые вы пытаетесь сопоставить.Например, для телевизоров вы, вероятно, хотите соответствовать размеру (xx") и семейству продуктов (BRAVIA LX900).

Это не дает вам решения вашего вопроса, но я боюсь ответа.

0 голосов
/ 09 сентября 2010

Обзор высокого уровня должен выглядеть следующим образом:

  • создать массив конечных результатов $ items
  • перебрать все найденные элементы на всех сайтах
  • для каждого проверьте, достаточно ли оно похоже на любое из существующих имен элементов в $ items
  • , если да, затем добавьте цену к этому ключу, если нет, то создайте новый и добавьте его туда

Вместо similar_text() вам следует рассмотреть возможность использования levenshtein(), который похож на практике, но довольно быстрый.

Вот некоторый (не проверенный, на месте) код:

$levThreshold = 3 ;

$_Prices = array() ;
foreach ($_Retreived as $website => $websiteItems) {
    $currName = $websiteItems[0] ;
    $currWebsite = $websiteItems[1] ;
    $currPrice = $websiteItems[2] ;

    $foundItemKey = false ;

    //check current price structure. Get $priceData by reference
    //so we can modify it in the loop and keep the changed instead 
    //of the loop copy.
    foreach ($_Prices as &$priceData) {

        if (isset($priceData[$website])) {
            //already done this
            continue ;
        }

        //check if this is the item name we are looping over
        $lev = levenshtein($priceData['Name'], $currName) ;

        if ($lev < $levThreshold) {
            //item exists, add price and break
            $priceData[$website] = $currPrice ;
            $foundItemKey = true ;
            break ;
        }

    }

    //if we haven't found the item key, create a new one
    if (!$foundItemKey) {
        $newItem = array() ;
        $newItem['Name'] = $currName ;
        $newItem[$website] = $currPrice ; 
        $_Prices[] = $newItem ;
    }

}

$levThreshold - это минимальное количество символов, которое должно отличаться в двух строках, чтобы их можно было считать разными.Вы можете настроить это соответственно.

...