2011-04-18 10 views
14

Tôi đang sử dụng tra cứu dựa trên AJAX cho tên mà người dùng tìm kiếm trong một hộp văn bản.Sử dụng JavaScript để thực hiện các kết quả khớp văn bản có/không có các ký tự có dấu

Tôi giả định rằng tất cả các tên trong cơ sở dữ liệu sẽ được chuyển thành bảng chữ cái châu Âu (nghĩa là không có chữ Kirin, Nhật Bản, Trung Quốc). Tuy nhiên, tên sẽ vẫn chứa các ký tự có dấu, chẳng hạn như ç, ê và thậm chí là č và ć.

Một tìm kiếm đơn giản như "Micic" sẽ không khớp với "Mičić" mặc dù - và kỳ vọng của người dùng là nó sẽ.

Tra cứu AJAX sử dụng cụm từ thông dụng để xác định đối sánh. Tôi đã sửa đổi so sánh cụm từ thông dụng bằng cách sử dụng hàm này trong một nỗ lực để khớp với nhiều ký tự có dấu trọng âm hơn. Tuy nhiên, đó là một chút vụng về vì nó không tính đến tất cả các nhân vật.

function makeComp (input) 
{ 
    input = input.toLowerCase(); 
    var output = ''; 
    for (var i = 0; i < input.length; i ++) 
    { 
     if (input.charAt (i) == 'a') 
      output = output + '[aàáâãäåæ]' 
     else if (input.charAt (i) == 'c') 
      output = output + '[cç]'; 
     else if (input.charAt (i) == 'e') 
      output = output + '[eèéêëæ]'; 
     else if (input.charAt (i) == 'i') 
      output = output + '[iìíîï]'; 
     else if (input.charAt (i) == 'n') 
      output = output + '[nñ]'; 
     else if (input.charAt (i) == 'o') 
      output = output + '[oòóôõöø]'; 
     else if (input.charAt (i) == 's') 
      output = output + '[sß]'; 
     else if (input.charAt (i) == 'u') 
      output = output + '[uùúûü]'; 
     else if (input.charAt (i) == 'y') 
      output = output + '[yÿ]' 
     else 
      output = output + input.charAt (i); 
    } 
    return output; 
} 

Ngoài chức năng thay thế như thế này, có cách nào tốt hơn không? Có lẽ để "deaccent" chuỗi được so sánh?

+0

Cảm ơn mã, tôi đã sử dụng chức năng của bạn để thay thế các nguyên âm có dấu trong văn bản nhập và làm việc tốt. – IgniteCoders

Trả lời

0

Trước tiên, tôi muốn đề nghị một lệnh switch thay vì một chuỗi dài của

if-else if ...

Sau đó, Tôi không chắc tại sao bạn không thích giải pháp hiện tại của mình. Nó chắc chắn là một trong sạch. Bạn có ý gì khi không tính đến "tất cả các nhân vật"?

Không có phương pháp chuẩn trong JavaScript để ánh xạ các chữ cái có dấu vào các chữ cái ASCII ngoài việc sử dụng thư viện của bên thứ ba, vì vậy thư bạn viết cũng tốt như bất kỳ thư nào.

Ngoài ra, "ß" tôi tin rằng bản đồ là "ss", không phải là một "s". Và hãy cẩn thận với "i" có và không có dấu chấm ở Thổ Nhĩ Kỳ - tôi tin rằng chúng đề cập đến các chữ cái khác nhau.

+0

Tôi thích tùy chọn 'haystack.indexOfIgnoreAccents (kim)' :) Tôi không thích phải làm nặng nâng ... – Philip

6

Không có cách nào dễ dàng hơn để "deaccent" mà tôi có thể nghĩ đến, nhưng thay của bạn có thể được sắp xếp hợp lý hơn một chút:

var makeComp = (function(){ 

    var accents = { 
      a: 'àáâãäåæ', 
      c: 'ç', 
      e: 'èéêëæ', 
      i: 'ìíîï', 
      n: 'ñ', 
      o: 'òóôõöø', 
      s: 'ß', 
      u: 'ùúûü', 
      y: 'ÿ' 
     }, 
     chars = /[aceinosuy]/g; 

    return function makeComp(input) { 
     return input.replace(chars, function(c){ 
      return '[' + c + accents[c] + ']'; 
     }); 
    }; 

}()); 
+0

Đây chắc chắn là một phiên bản thanh lịch của chức năng của tôi. – Philip

1

tôi đã thực hiện một phiên bản thử nghiệm này:

String.prototype.strip = function() { 
    var translate_re = /[öäüÖÄÜß ]/g; 
    var translate = { 
    "ä":"a", "ö":"o", "ü":"u", 
    "Ä":"A", "Ö":"O", "Ü":"U", 
    " ":"_", "ß":"ss" // probably more to come 
    }; 
    return (this.replace(translate_re, function(match){ 
     return translate[match];}) 
    ); 
}; 

Sử dụng như:

var teststring = 'ä ö ü Ä Ö Ü ß'; 
teststring.strip(); 

chí này sẽ thay đổi String để a_o_u_A_O_U_ss

1

Tôi đang tìm kiếm một cái gì đó tương tự, nhưng thay vì tạo ra một biểu thức chính quy, tôi chỉ muốn thay thế các ký tự có dấu cho tương đương ASCII của chúng. Lấy cảm hứng từ câu trả lời của 999 và một bài báo tại A List Apart (http://www.alistapart.com/articles/accent-folding-for-auto-complete/) Tôi đã đến với chức năng sau. Nó có thể được sửa đổi cho việc triển khai cụ thể của khóa học:

var accent_fold = (function() { 
    var accent_map = { 
     'à': 'a', 'á': 'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', // a 
     'ç': 'c',             // c 
     'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',      // e 
     'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i',      // i 
     'ñ': 'n',             // n 
     'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ø': 'o', // o 
     'ß': 's',             // s 
     'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u',      // u 
     'ÿ': 'y'             // y 
    }; 

    return function accent_fold(s) { 
     if (!s) { return ''; } 
     var ret = ''; 
     for (var i = 0; i < s.length; i++) { 
      ret += accent_map[s.charAt(i)] || s.charAt(i); 
     } 
     return ret; 
    }; 
}()); 

sử dụng:

var someText = "lôõk mä, nø hånds!"; 
someText = accent_fold(someText); 
// someText now contains: "look ma, no hands!" 
10

Đến khi chủ đề cũ này và nghĩ rằng tôi muốn thử tay của tôi lúc làm một chức năng nhanh chóng. Tôi đang dựa vào thứ tự của các biến ORs được phân tách bằng đường ống khi chúng khớp nhau trong hàm replace() đang gọi.Mục tiêu của tôi là sử dụng hàm replace() của hàm regex thực hiện tiêu chuẩn, sử dụng càng nhiều càng tốt, để xử lý nặng có thể diễn ra trong không gian tối ưu hóa trình duyệt cấp thấp, thay vì so sánh javascript char-by-char đắt tiền .

Đó không phải là khoa học ở tất cả, nhưng cũ Huawei IDEOS điện thoại Android của tôi là chậm chạp khi tôi cắm các chức năng khác trong chủ đề này để autocomplete của tôi, trong khi chức năng này kéo khóa dọc:

function accentFold(inStr) { 
    return inStr.replace(/([àáâãäå])|([ç])|([èéêë])|([ìíîï])|([ñ])|([òóôõöø])|([ß])|([ùúûü])|([ÿ])|([æ])/g, function(str,a,c,e,i,n,o,s,u,y,ae) { if(a) return 'a'; else if(c) return 'c'; else if(e) return 'e'; else if(i) return 'i'; else if(n) return 'n'; else if(o) return 'o'; else if(s) return 's'; else if(u) return 'u'; else if(y) return 'y'; else if(ae) return 'ae'; }); 
} 

Nếu bạn một jQuery dev, đây là một ví dụ hữu ích về cách sử dụng hàm này; bạn có thể sử dụng: icontains giống như cách bạn muốn sử dụng: chứa trong một selector:

jQuery.expr[':'].icontains = function(obj, index, meta, stack){ return accentFold((obj.textContent || obj.innerText || jQuery(obj).text() || '').toLowerCase()).indexOf(accentFold(meta[3].toLowerCase())) >= 0; };