为了账号安全,请及时绑定邮箱和手机立即绑定

如何找到最接近的匹配数组

如何找到最接近的匹配数组

PHP
SMILET 2023-07-07 10:46:05
家具店网站的顾客可以选择产品并将其添加到“款式书”中。每件产品都属于一种“风格”。这家家具店有一些造型师,每个人都制作了自己的风格书来代表他们的风格和专业知识。我希望能够找到最符合客户造型手册的造型师。对于每个款式书,我都会统计每种款式的产品数量。$stylists = [    'Nanda'     => [        'Design'  => 20,        'Retro'   => 0,        'Rustiek' => 0,    ],    'Angelique' => [        'Design'  => 0,        'Retro'   => 20,        'Rustiek' => 0,    ],    'Lissy'     => [        'Design'  => 10,        'Retro'   => 10,        'Rustiek' => 0,    ],];客户的样式书也是如此:$customer = [    'Design'  => 15,    'Retro'   => 10,    'Rustiek' => 0,];在这种情况下,Lissy 应该是最佳匹配。产品的数量并不重要,因为这取决于造型师的活跃程度。更重要的是造型师能匹配大部分顾客的风格。例如:'Stylist'     => [    'Design'  => 10,    'Retro'   => 10,    'Rustiek' => 0,]应该还是比更好的匹配'Stylist'     => [    'Design'  => 300,    'Retro'   => 0,    'Rustiek' => 180,]我曾尝试根据客户风格书的重要性顺序为造型师的风格书评分和百分比,但仍然无法 100% 获得最佳匹配。谷歌也没有给我任何帮助。
查看完整描述

1 回答

?
神不在的星期二

TA贡献1963条经验 获得超6个赞

正如我们已经讨论过的,您的模型的问题在于它依赖于产品的数量。但我们需要的是造型师所使用的风格的指标。换句话说,我们消除了计数并将其替换为相对加权的指标(在本例中为百分比)。例如,一位造型师的产品组合包括:


[

    style1 => 30,

    style2 => 10,

    style3 => 5

]

产品数量45 = 30 + 10 + 5将产生如下的样式配置文件:


[

    style1 => 0.66,

    style2 => 0.22,

    style3 => 0.11

]

为了将 stylist-style-profile 与 client-style-profile 相匹配,我们需要对 client-stylebook 执行相同的操作[15, 10, 0]:


[

    style1 => 0.60

    style2 => 0.40

    style3 => 0.00

]

其背后的想法是,我们评估设计师如何受到某种风格的影响,并且对于我们想要找到最合适的设计师的产品来说,结果可能非常相似。


如果造型师制作的产品风格并非我们真正需要的搭配,我们会使用加权相对因子(例如 0.11)来评价这一事实。这并不重要,但我们仍然承认设计可能有些偏差。


因此,如果设计师有很多我们不寻找的某种风格的产品,它不会对结果产生太大的改变。


如果这有帮助并且您想更改任何内容,请告诉我。从这里我们还可以实施其他选项和规则。


您可以在下面找到我的评级模型。


<?php


class RatingModel {

    private $name;

    private $preferences;

    private $preferencesWeighted;


    public function RatingModel($name, array $preferences) {

        $this->name = $name;

        $this->preferences = $preferences;

        $this->init();

    }


    private function init() {

        $total = 0;

        foreach ($this->preferences as $value) {

            $total += $value;

        }

        if ($total > 0) {

            foreach ($this->preferences as $value) {

                $this->preferencesWeighted[] = $value / $total;

            }

        } else {

            $this->preferencesWeighted = array_fill(0, sizeof($this->preferences), 0);

        }

    }


    public function getName() {

        return $this->name;

    }


    public function getPreferences() {

        return $this->preferences;

    }


    public function getPreferencesWeighted() {

        return $this->preferencesWeighted;

    }


    public function distanceToModel($ratingModel) {

        $delta = [];

        for ($i = 0; $i < sizeof($this->preferencesWeighted); $i++) {

            $delta[] = abs($this->preferencesWeighted[$i] - $ratingModel->getPreferencesWeighted()[$i]);

        }

        return $delta;

    }


    public function scoreToModel($ratingModel) {

        $distanceToModel = $this->distanceToModel($ratingModel);

        $score = [];

        foreach ($distanceToModel as $value) {

            $score[] = $value * $value;

        }

        return sqrt(array_sum($score));

    }

}


$customer = new RatingModel('Customer', [15, 10, 0]);

$nanda = new RatingModel('Nanda', [20, 0, 0]);

$angelique = new RatingModel('Angelique', [0, 20, 0]);

$lissy = new RatingModel('Lissy', [10, 0, 0]);

$mary = new RatingModel('Mary', [0, 0, 0]);

$max = new RatingModel('Max', [12, 0, 5]);

$simon = new RatingModel('Simon', [17, 2, 5]);

$manuel = new RatingModel('Manuel', [17, 8, 10]);

$betty = new RatingModel('Betty', [16, 9, 5]);

$sally = new RatingModel('Sally', [15, 10, 4]);

$peter = new RatingModel('Peter', [16, 9, 1]);


$stylists = [$nanda, $angelique, $lissy, $mary, $max, $simon, $manuel, $betty, $peter, $sally];


$relativeToClient = [];

foreach ($stylists as $stylist) {

    $relativeToClient[] = [

        'stylist' => $stylist->getName(),

        'distance' => $stylist->distanceToModel($customer),

        'score' => $stylist->scoreToModel($customer)

    ];

}


echo '<pre>';

print_r($stylists);

echo '<hr>';

print_r($customer);

echo '<hr>';

print_r($relativeToClient);

echo '<hr>from best fit to worst (low score means low delta)<hr>';

$results = array_column($relativeToClient, 'score', 'stylist');

asort($results);

print_r($results);

echo '</pre>';

下面是结果(值越低越好):


Array

(

    [Peter] => 0.067936622048676

    [Sally] => 0.1700528000819

    [Betty] => 0.20548046676563

    [Manuel] => 0.35225222874108

    [Simon] => 0.3942292057505

    [Max] => 0.50765762377392

    [Nanda] => 0.56568542494924

    [Lissy] => 0.56568542494924

    [Mary] => 0.7211102550928

    [Angelique] => 0.84852813742386

)

如果我们看看两个最合身的造型师,我们会发现彼得胜过莎莉,因为莎莉有更多不同风格的产品。


Sally: [15, 10, 4]

Peter: [16, 9, 1]

您可能还注意到,Nanda 和 Lissy 的得分相同:


Nanda: [20, 0, 0]

Lissy: [10, 0, 0]


// relatively, for both => [1.00, 0.00, 0.00]

他们都被认为同样合适。与第一种款式相比,Nanda 多了 5 个产品,Lissy 少了 5 个产品,但这并不重要,因为他们都只提供一种款式,重要的是:他们距离理想的客户风格有多远。


您还可以实现逻辑,以便在比较时没有偏差因素并且更加严格。在这种情况下,您可能想要排除一些参数。


例如,只是比较[15, 10]-[16, 9]在这种情况下,莎莉实际上会获胜,因为在偏好方面,她与客户没有差异:


莎莉:


[

    style1 => 0.60,

    style2 => 0.40

]

彼得:


[

    style1 => 0.64,

    style2 => 0.36

]


查看完整回答
反对 回复 2023-07-07
  • 1 回答
  • 0 关注
  • 137 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号