te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - Sort a list of strings given a predefined order - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Sort a list of strings given a predefined order - Stack Overflow

programmeradmin2浏览0评论

I have an array of colors that I'd like to sort into order. However, I don't want to sort them using their "natural" ordering, but rather to keep them in this order:

var order = ['white', 'yellow', 'violet', 'blue', 'orange', 'red', 'maroon', 'brown', 'black'];

So, for example, sorting this array

var items = ['blue', 'violet', 'white', 'black', 'orange'];

should give back

['white', 'violet', 'blue', 'orange', 'black'];

Here's what I have so far:

var itemsInOrder = [];

for (var i=0; i<order.length; i++) {
    if (items.indexOf(order[i]) > -1) {
        itemsInOrder.push(order[i]);
    }
}

I'm not sure how well it scales - what if order has 100 or 1000 elements but 'items' has 10?

What is a good, scalable way to acplish this?

I have an array of colors that I'd like to sort into order. However, I don't want to sort them using their "natural" ordering, but rather to keep them in this order:

var order = ['white', 'yellow', 'violet', 'blue', 'orange', 'red', 'maroon', 'brown', 'black'];

So, for example, sorting this array

var items = ['blue', 'violet', 'white', 'black', 'orange'];

should give back

['white', 'violet', 'blue', 'orange', 'black'];

Here's what I have so far:

var itemsInOrder = [];

for (var i=0; i<order.length; i++) {
    if (items.indexOf(order[i]) > -1) {
        itemsInOrder.push(order[i]);
    }
}

I'm not sure how well it scales - what if order has 100 or 1000 elements but 'items' has 10?

What is a good, scalable way to acplish this?

Share Improve this question edited Aug 27, 2015 at 20:17 templatetypedef 373k111 gold badges942 silver badges1.1k bronze badges asked Jun 17, 2014 at 22:44 BaltoStarBaltoStar 8,99719 gold badges65 silver badges105 bronze badges 4
  • 6 items.sort(function(a,b){return order.indexOf(a)-order.indexOf(b);} – Shmiddty Commented Jun 17, 2014 at 22:49
  • var itemsInOrder = items.slice().sort(...) if you don't want to mutate items – Shmiddty Commented Jun 17, 2014 at 22:51
  • @Shmiddty could you explain more how items.sort() mutates items ? – BaltoStar Commented Jun 18, 2014 at 18:48
  • Array.prototype.sort will update the indices of the array being sorted instead of creating and returning a new (sorted) array. – Shmiddty Commented Jun 19, 2014 at 17:56
Add a ment  | 

3 Answers 3

Reset to default 12

As @Shmiddty pointed out in a ment, one simple way to do this is to use the library sort function with a custom parator, like this:

items.sort(function(a,b) {
   return order.indexOf(a) - order.indexOf(b);
});

I'd start with that. If it's fast enough, great! Go with it.

From a time plexity perspective, let's imagine that you have a list of n elements to sort and the master ordering has k elements in it. Then calling sort with a custom parator will make O(n log n) parisons, each of which takes time O(k) due to the cost of scanning over the list. That gives a runtime of O(kn log n). Assuming k is small - that is, your master list isn't too long - this is perfectly fine.

If k is large - for example, if you have a fixed ordering of all cities in the world, or something like that - then this approach is not likely to scale well. In that case, you may want to add another layer of indirection to the problem by creating a dictionary directly mapping everything to be sorted to its index. Here's one way to do this:

var indexMap = {};
for (var i = 0; i < order.length; i++) {
    indexMap[order[i]] = i;
}

items.sort(function(a,b) {
   return indexMap[a] - indexMap[b];
});

This has time plexity O(k + n log n), so for very large k it's likely to be appreciably faster.

One thing in addition to the answer by templatetypedef is that if your predefined is "partial" e.g. some items in the list cannot be sorted by your predefined order, then you could separate these out of your list and then concatenate them back at the end of the list afterwards e.g.

var items = [3, 2, 3, 2, 1, 4, 5, 1, 2, 3]
var order = [1, 2, 3]
var unordered = items.filter(t => order.indexOf(t) === -1);
var ordered = items.filter(t => order.indexOf(t) !== -1);
ordered.sort(function(a,b) {
   return order.indexOf(a) - order.indexOf(b);
});
var final = ordered.concat(unordered)
console.log(final)
// [ 1, 1, 2, 2, 2, 3, 3, 3, 4, 5 ]

If you don't take this step, then the sort will actually put the unordered items at the front of the list and I didn't have any idea how to change it to move them back to the end without filtering them out first.

If somebody is looking for a simpler code than Colin D to sort the array and add unknown items at the end, here's another example:

let list = ["A", "F", "Banana", "rules", "L", "Juice", "Z"]
let order = ["Banana", "Juice", "rules"]

list.sort((a, b) => {
  if (order.indexOf(a) === -1) return 1
  if (order.indexOf(b) === -1) return -1
  return order.indexOf(a) - order.indexOf(b)
})

console.log(list)

This will log: ["Banana", "Juice", "rules", "A", "F", "L", "Z"]

发布评论

评论列表(0)

  1. 暂无评论