【问题标题】:PHP array_unique returns duplicatePHP array_unique 返回重复
【发布时间】:2016-10-20 17:49:53
【问题描述】:

这是我的桌子tracks

+---+--------------------+
| id|                 tag|
+---+--------------------+
| 1 |              dance,|
| 2 |        dance,tecno,|
| 3 |        dance,hihop,|
| 4 |                rap,|
| 5 |            country,|
| . |                 ...|
+---+--------------------+

我试过这个($value 是我的查询):

$tags = $this->db->query(sprintf("SELECT `tag`, `id` FROM `tracks` WHERE `tag` LIKE '%s' GROUP BY `tag` DESC LIMIT %s, %s", '%'.$this->db->real_escape_string($value).'%', $this->db->real_escape_string($start), $per_page));

while($row = $tags->fetch_assoc()) {
    $rows[] = $row;
}

$tags = explode(',', $row['tag']);
$rows = array_unique(array_map('strtolower', $tags));

foreach($rows as $row) {
    if(stripos($row, $value) !== false) {
        $tag_output .= '<div class="hashtag-inner">
                            '.$row.'
                        </div>';
    }
}

从这个例如。预期的输出是:dance, tecno, hiphop, rap, country 带有所有唯一标签,而不是标签 dance 的多个输出。 我的输出有什么问题?

【问题讨论】:

  • $this->db->real_escape_string($value) 中的 value 或 $value 是什么?
  • @scaisEdge 这是来自搜索输入的搜索查询
  • array_unique 查看整个字符串,它不认为dance,dance,techno 是重复的。
  • @Barmar 我在想那个……那我该怎么办?

标签: php mysql


【解决方案1】:

您需要在处理每一行的循环中调用explode()。您的代码只是爆炸了最后一行。

$rows = array();
while ($row = $tags->fetch_assoc()) {
    $tags = explode(',', $row['tag']);
    $rows = array_merge($rows, $tags);
}
$rows = array_unique(array_map('strtolower', array_filter($rows)));

array_filter() 用于删除来自标记列表末尾的, 的空字符串。

但是,最好的长期解决方案是规范化您的数据库架构,这样您就不会在表中存储逗号分隔的列表。您应该有一个表格,其中每个标签都位于单独的行中。

【讨论】:

    【解决方案2】:

    我认为你需要这样的东西

    $tags = $this->db->query(sprintf("SELECT `tag`, `id` FROM `tracks` WHERE `tag` LIKE '%s' GROUP BY `tag` DESC LIMIT %s, %s", '%'.$this->db->real_escape_string($value).'%', $this->db->real_escape_string($start), $per_page));
    
    $str = '';
    while($row = $tags->fetch_assoc()) {
        // combine all tags from "tag" column
        $str .= $row['tag'];
    }
    
    $tags = explode(',', $str);
    $rows = array_unique(array_map('strtolower', $tags));
    
    foreach($rows as $row) {
        if(stripos($row, $value) !== false) {
            $tag_output .= '<div class="hashtag-inner">
                                '.$row.'
                            </div>';
        }
    }
    

    【讨论】: