2015-01-12 19 views
5

Tôi muốn sắp xếp một bảng theo thứ tự bảng chữ cái. Ngoại trừ số.Bảng phân loại Lua theo thứ tự abc, ngoại trừ số

Đoạn code dưới đây cho thấy cách bảng được sắp xếp với chức năng so sánh:

function(a,b) return a.N < b.N end 

Cung cấp cho tôi:

obj = { 
    [1] = { 
     ["N"] = "Green 1"; 
    }; 
    [2] = { 
     ["N"] = "Green 11"; 
    }; 
    [3] = { 
     ["N"] = "Green 2"; 
    }; 
    [4] = { 
     ["N"] = "Red 1"; 
    }; 
} 

Nhưng tôi muốn nó được sắp xếp như thế này:

obj = { 
    [1] = { 
     ["N"] = "Green 1"; 
    }; 
    [2] = { 
     ["N"] = "Green 2"; 
    }; 
    [3] = { 
     ["N"] = "Green 11"; 
    }; 
    [4] = { 
     ["N"] = "Red 1"; 
    }; 
} 

Có thể không?

+0

Remove tất cả các số từ khóa trước khi bạn sắp xếp? Chỉ sắp xếp từ đầu tiên? vv Nếu bảng của bạn là lớn hoặc bạn sẽ làm điều này thường xuyên giữ một bộ nhớ cache của "phím sắp xếp" bạn tạo ra có thể là một ý tưởng tốt quá. –

Trả lời

3

Đã đăng bài này ban đầu, nhưng giải pháp được đăng bởi lhf đã trả lời câu hỏi của bạn. Vì bạn vẫn gặp sự cố, hãy thử sau.

local function cmp(a, b) 
    a = tostring(a.N) 
    b = tostring(b.N) 
    local patt = '^(.-)%s*(%d+)$' 
    local _,_, col1, num1 = a:find(patt) 
    local _,_, col2, num2 = b:find(patt) 
    if (col1 and col2) and col1 == col2 then 
     return tonumber(num1) < tonumber(num2) 
    end 
    return a < b 
end 

local obj = { 
    { N = '1'   }, 
    { N = 'Green1'  }, -- works with optional space 
    { N = 'Green'  }, -- works when doesn't fit the format 
    { N = 'Sky blue99' }, 
    { N = 'Green 11' }, 
    { N = 'Green 2'  }, 
    { N = 'Red 02'  }, -- works when has leading zeros 
    { N = 'Red 01' }, -- works with padding spaces 
    { N = 'Sky blue 42' }, -- works with multi-word color names 
    { N = 99   }, -- works with numbers 
} 

table.sort(obj, cmp) 
for i,v in ipairs(obj) do 
    print(i, v.N) 
end 

Prints:

1 1 
2 99 
3 Green 
4 Green1 
5 Green 2 
6 Green 11 
7 Red 01 
8 Red 02 
9 Sky blue 42 
10 Sky blue99 
+0

Cảm ơn, điều này hoạt động tốt hơn. Thay đổi mẫu thành: ''^ (% D +) (% d +) $'' để cho phép '{N = 'Green1'},' dường như hoạt động nhưng có thể đã bỏ qua một cái gì đó. – Dreanh

+0

@Dreanh Mô hình đó có vẻ tốt và nên hoạt động miễn là không có bất kỳ chữ số nào trong tên màu, (. +) Hoạt động cho bất kỳ ký tự nào. – Adam

+0

Ok, cảm ơn. Nếu tôi sử dụng ''^ (. +) (% D +) $'' hoặc ''^ (% g) (% d +) $'' nó không hoạt động. – Dreanh

6

Hãy thử điều này:

local function split(a) 
    local x,y=a.N:match("(%S+)%s+(%S+)") 
    return x,tonumber(y) 
end 

table.sort(obj, 
    function (a,b) 
     local a1,a2=split(a) 
     local b1,b2=split(b) 
     return a1<b1 or (a1==b1 and a2<b2) 
    end 
) 
+0

Cảm ơn! Điều đó làm việc giống như tôi muốn nó! – Dreanh

+0

Đã xảy ra sự cố, không đề cập đến một số chuỗi trong bảng không có số. Vì vậy, tôi nhận được một lỗi. – Dreanh

+0

Nhận lỗi trên dòng này: 'trả về a1 Dreanh

3

@ giải pháp lhf của nên làm việc cho bạn, mặc dù bạn có thể cần phải xem xét nếu bạn cần để xử lý các trường hợp góc, giống như so sánh "xanh 1" với "Green 02" hay "Green 2 "với" Màu xanh lá cây 02 ". Tôi đã xem xét một số phương pháp để thực hiện phân loại alphanum và so sánh kết quả của chúng trong một blog post. Bạn cũng có thể kiểm tra số discussion on the lua mail list về chủ đề này.

Các vấn đề liên quan