【问题标题】:PHP Arrays - Sort and PriorityPHP 数组 - 排序和优先级
【发布时间】:2013-01-02 21:03:18
【问题描述】:

在我的网站上,用户可以用不同的语言发布他们的个人资料,比如 LinkedIn,现在我们在用户的名字之间进行搜索,例如我们搜索:“ar”,我们会查看所有个人资料语言,我们将有一个数组作为回报:

array
  0 => string '20=>en' (length=5)
  1 => string '42=>en' (length=5)
  2 => string '20=>fa' (length=5)
  3 => string '42=>sp' (length=5)
  4 => string '12=>fr' (length=5)
  5 => string '83=>ar' (length=5)
  6 => string '160=>sp' (length=5)

上面的数组显示我们有 6 个配置文件与我们在不同语言中的搜索“ar”相匹配,上面的数组显示:

0 => Match found for User with ID = 20 in English Lang(en) profile
1 => Match found for User with ID = 42 in English Lang(en) profile
2 => Match found for User with ID = 20 in Farsi Lang(fa) profile
3 => Match found for User with ID = 42 in Spanish Lang(sp) profile
4 => Match found for User with ID = 12 in French Lang(fr) profile
5 => Match found for User with ID = 83 in Arabic Lang(ar) profile
6 => Match found for User with ID = 160 in Spanish Lang(sp) profile

现在,我们想显示结果,但事实上,正如您在结果中看到的那样,我们在 EnglishEnglishFarsi 语言,但我们不能显示同一个人的 2 个结果!所以我们需要放弃腋窝结果,所以上面的数组应该根据用户 ID 和语言的优先级进行过滤和唯一化,我对语言的优先级是:

  1. $_SESSION['my_lang'];
  2. 英语(英文);
  3. 兰德();

输入“ar”作为他的搜索查询的人有一个$_SESSION['my_lang'],因此在结果数组中的用户的结果为$_SESSION['my_lang'],我们应该保留该结果并放弃其他匹配项同一个人。

$_SESSION['my_lang']之后,我们的优先级应该是EN lang,如果一个人有N种语言的结果,但是我们在$_SESSION['my_lang']中找不到匹配,那么我们应该将结果保留在en lang清除该人的其余结果

在上面的优先级之后,实际上什么都不重要了,我们只需要保留那个人的一个结果,去掉那个人的其他结果,所以语言应该随机选择.. .

我不知道如何做到这一点, 我将不胜感激。


在我的示例中,我有一个类似的数组:

array
  0 => string '20=>en' (length=5)
  1 => string '42=>en' (length=5)
  2 => string '20=>fa' (length=5)
  3 => string '42=>sp' (length=5)
  4 => string '12=>fr' (length=5)
  5 => string '83=>ar' (length=5)
  6 => string '160=>sp' (length=5)

但在您的示例中,您有一个类似的数组:

$users = array(
  array('id'=> 20, 'lang'=>'en'),
  array('id'=> 42, 'lang'=>'en'),
  array('id'=> 20, 'lang'=>'fa'),
  array('id'=> 42, 'lang'=>'sp'),
  array('id'=> 12, 'lang'=>'fr'),
  array('id'=> 83, 'lang'=>'ar'),
  array('id'=> 160, 'lang'=>'sp'));

我应该如何使我的数组看起来像你的数组,这样你的代码才能工作..?谢谢

【问题讨论】:

  • 听起来您可能希望将此限制/排序包含在执行搜索查询的任何内容中,而不是返回的数据数组中。
  • @MattRazza 搜索查询真的很复杂,我只是想通了很多连接和过滤...我更喜欢限制结果,知道吗?

标签: php arrays


【解决方案1】:

可能有更好(更有效)的方法来做到这一点,但这里有一种方法。分 3 步完成。 (1)创建一个语言数组,(2)排序用户数组,基于语言数组,(3)使用户数组具有唯一用户。

注意 第二步使用匿名函数,所以如果 PHP v

用户数组

$users = array(
               array('id'=> 20, 'lang'=>'en'),
               array('id'=> 42, 'lang'=>'en'),
               array('id'=> 20, 'lang'=>'fa'),
               array('id'=> 42, 'lang'=>'sp'),
               array('id'=> 12, 'lang'=>'fr'),
               array('id'=> 83, 'lang'=>'ar'),
               array('id'=> 160, 'lang'=>'sp'));

第 1 步

//Create an Array of Languages
$langs[0] = $_SESSION['my_lang']; // Set $_SESSION['my_lang'] as 1st
if($langs[0] != 'en'){
    $langs[1] = 'en';} // Set en as 2nd, if not already as 1st

//Add remainder of User languages to Languages
shuffle($users);  // This randomizes the $user array so the rest of the languages are random. Can be removed if randomizing the rest of the languages is not necessary.
foreach ($array as $lang) {
    if(!in_array($lang['lang'],$langs))
        $langs[] =$lang['lang'];
}

第 2 步与 php v >= 5.3 一起使用 - 使用匿名函数

//Reorder the User array, bases off Language array
$keys = array_flip($langs);
usort($users, function($a, $b) use($keys)
{
    return $keys[$a['lang']] - $keys[$b['lang']];
});

第 2 步 与 php v 一起使用

//Reorder the User array, bases off Language array
$keys = array_flip($langs);
function custom($a,$b){
   global $keys;
   return $keys[$a['lang']] - $keys[$b['lang']];
}
usort($users, "custom");

第 3 步

//Make the User array unique
$temp_array = array();
foreach ($users as &$v) {
    if (!isset($temp_array[$v['id']]))
        $temp_array[$v['id']] =&$v;
}
$users = array_values($temp_array);

phpFiddle w/ 第 2 步 for php v >= 5.3 - http://phpfiddle.org/main/code/xva-dzn

phpFiddle w/ 第 2 步 for php v http://phpfiddle.org/main/code/p02-r6b


编辑
假设你的数组 -

array
  0 => string '20=>en' (length=5)
  1 => string '42=>en' (length=5)
  2 => string '20=>fa' (length=5)
  3 => string '42=>sp' (length=5)
  4 => string '12=>fr' (length=5)
  5 => string '83=>ar' (length=5)
  6 => string '160=>sp' (length=5)

var_dump() 类似这样的东西-

$returned = array(
  0 => '20=>en',
  1 => '42=>en',
  2 => '20=>fa',
  3 => '42=>sp',
  4 => '12=>fr',
  5 => '83=>ar',
  6 => '160=>sp');

使用explode()for() 循环,您可以将数组更改为要在上述步骤中使用的多定义数组。

$users = array();
for($i=0;$i<count($returned);$i++){
     $split_returned = explode("=>",$returned[$i]); // split up each line at the '=>'
     $users[$i]['id'] = $split_returned[0];   // set the 'id'
     $users[$i]['lang'] = $split_returned[1];}  // set the 'lang'

【讨论】:

  • 优秀的答案!这会使用很多 CPU/Ram 吗!?有什么更有效的方法来做到这一点?
  • 不幸的是,我对 CPU/Ram 基准测试帮不上什么忙,因为我对此并不精通。我用当前数组运行了 3 次,运行时间相当短 - 0.000227928161621 / 0.000319004058838 / 0.000295877456665,但我不知道它会对 CPU/Ram 的使用产生什么影响,以及如何它会随着更大的数组而改变。此外,关于更有效的方法来实现这一点。我唯一的其他建议是找到一种方法将其添加到您的查询中,但正如您在上面的评论中提到的,您的查询已经很复杂。所以我不确定还有其他选择。
  • 我假设您的数组是您实际数组的var_dump()。如果是这样,我已经发布了对我的问题的编辑,展示了如何使用 explode()for() 循环更改您的数组。
  • 抱歉再次打扰,但是我的服务器PHP版本似乎不支持Step 2,有没有其他方法可以做到PHP &lt; 5.3中的Step 2,非常感谢
  • 我已经更新了第 2 步并添加了如何使用 php v
猜你喜欢
  • 2018-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多