人性化排序

对于大部分产品来说,搜索功能是必不可少的。有搜索的地方,就有排序。对文本信息的排序没有数值排序来的那么直观,对搜索到的信息,通常的展示策略有三种:

    1. 按自然顺序排列;
    2. 按相似度由高至低排列;
    3. 按信息的活性(热度)进行排列。

当然,最糟糕也最常见的是下面这种方式:完全不做任何排序。

最近碰到的一个应用场景让我对此进行了反思。我们的实时公交查询系统为其他App开发者提供了这样的一个API:根据用户的搜索内容返回线路名称。现在不妨假设用户输入了一个 «1»,后台进行查询,找到所有与 «1» 有关的线路,最开始我们的输出是无序的:

               81,  17, 201路, 快线1号, 11, 1路, 168 , 高快巴士1号线 ....

结果竟然返回了221个与1有关的线路,这样的展示结果显然是会让用户骂人的。后来决定先返回所有 «1» 开头的线路,其余自然排序:

              11, 17, 168, 1路,201路, 81, 高快巴士1号线,快线1号 ...

这次结果好了很多,但是1路竟然排在168后面,仍然会让人不爽,所以按照相似度进行排序:

              11,17,81,1路,168,201路,.... 快线1号,高快巴士1号线

这次达到了预想的效果,但把快线1号,高快巴士1号线这样比较难记,难输入的线路放到了最后,实际上用户如果只输入 «1» 进行查询,很可能要找的就是 “快线1号” 或者 “高快巴士1号线”,所以把这种输入成本高的线路挪到了前面:

              11, 17, 1路,168,快线1号,高快巴士1号线,201路,81 ....

实现代码:

		Arrays.sort(sortedLineNames, new Comparator<Object>(){  
            @Override  
            public int compare(Object b1, Object b2) {  
            	String s1 = (String)b1;
            	String s2 = (String)b2;
            	
            	if (s1.startsWith(searchString) && !s2.startsWith(searchString)) {
            		return -1;
            	} 
            	else if(!s1.startsWith(searchString) && s2.startsWith(searchString)) {
            		return 1;
            	} 
            	else if (! s1.startsWith(searchString) && !s2.startsWith(searchString)) {
            	       return s2.compareTo(s1);
            	}
            	else {
            	       return s1.compareTo(s2);
            	}
            }             
        });                                                                            

当然,Java 8引入lambda之后,可以简写为:

       Arrays.sort(sortedLineNames, 
                   (s1, s2) ->  
                     s1.startsWith(searchString) && !s2.startsWith(searchString) ? -1 :
                    !s1.startsWith(searchString) &&  s2.startsWith(searchString) ?  1 :
                    !s1.startsWith(searchString) && !s2.startsWith(searchString) ?  s2.compareTo(s1) : 
                     s1.compareTo(s2));

在多数情况下,这些策略已经可以组合出不错的效果了,但这就足够了么? 用户搜索的目的是希望找到对自己有价值的信息,而排序最终是为了讨好用户:在信息呈现之前,猜测一下用户的心理,认为用户最想要什么,就把什么放在前面,让用户用最少的时间成本获取最有价值的信息。所以为了更懂用户,可能还需要对日志进行分析,统计每条线路的搜索频率,得出线路的活跃程度,每次尽可能把活性比较大的线路放置在返回结果的前面。更进一步,可以看看线路活性的分布情况和规律,得出更有指导性的结论。

写到这里,突然感觉排序分明就是一种人工智能的东东,这也无怪乎那些做搜索的公司都铆足了劲儿搞深度学习。 在这样一个时代,不懂人心估计就得死吧。

Tags// ,
More Reading