2012-02-09 25 views
7

Tôi đang làm việc trên điều lọc này, nơi tôi có khoảng 50-100 mục danh sách. Và mỗi mục có đánh dấu như thế này:Tìm kiếm mờ JavaScript

<li> 
    <input type="checkbox" name="services[]" value="service_id" /> 
    <span class="name">Restaurant in NY</span> 
    <span class="filters"><!-- hidden area --> 
    <span class="city">@city: new york</span> 
    <span class="region">@reg: ny</span> 
    <span class="date">@start: 02/05/2012</span> 
    <span class="price">@price: 100</span> 
    </span> 
</li> 

Tôi tạo ra đánh dấu như thế này bởi vì tôi initally sử dụng List.js

Vì vậy, có lẽ bạn đoán đã có, những gì tôi muốn là để thực hiện tìm kiếm như thế này: @region: LA @price: 124 và vân vân . Vấn đề là tôi cũng muốn hiển thị nhiều hơn một mục, để chọn nhiều hơn một mục :)

Tôi cho rằng điều này cần tìm kiếm mờ, nhưng vấn đề là tôi không tìm thấy bất kỳ chức năng nào.

Bất kỳ ý tưởng hoặc điểm xuất phát nào?

// chỉnh sửa: bởi vì tôi có một số lượng khá nhỏ các mặt hàng, tôi muốn một giải pháp phía khách hàng.

+1

Kiểm tra này ra: http://code.google.com/p/yeti-witch/ - Có thể là sự giúp đỡ. – techfoobar

+0

Ngoài ra, hãy xem liệu yêu cầu của bạn có cho phép bạn di chuyển phần tìm kiếm mờ sang phía máy chủ (với AJAX) hay không - Nếu vậy, làm việc đó bằng cách sử dụng solr sẽ là điều dễ nhất. Ngoài thực tế là bạn có thể tìm kiếm thông qua hàng ngàn mục trong thời gian không. http://lucene.apache.org/solr/ – techfoobar

+0

Techfoobar: cảm ơn, nhưng yeti dường như giống java hơn javascript. Tôi không thể tìm ra cách sử dụng nó trên mã hiện có của mình. Ngoài ra, solr có vẻ là java quá. Tôi cần một cái gì đó phía khách hàng hoặc PHP. –

Trả lời

5

Một năm sau, List.js có một plugin tốt đẹp cho fuzzy search hoạt động khá tuyệt vời.

+2

nó thực hiện tìm kiếm nhưng nó không thực sự là" tìm kiếm mờ " ví dụ như trong bản demo của chúng" mờ " "truy vấn:" bruwo "không tìm thấy" Guybrush Threepwood "... – tborychowski

+0

Bạn có thể chỉ định mức độ mờ bạn muốn tìm kiếm. Bạn có thể nhập bruw và" Guybrush Treepwood "hiển thị. Đó là khi bạn nhận được hai ký tự từ từ thứ hai mà kết quả được lọc ra. – user393274

1

Tôi có một chức năng nhỏ, tìm kiếm một chuỗi trong một mảng (ít nhất là đối với tôi nó tạo ra kết quả tốt hơn so với Levenshtein):

function fuzzy(item,arr) { 
    function oc(a) { 
    var o = {}; for (var i=0; i<a.length; i++) o[a[i]] = ""; return o; 
    } 
    var test = []; 
    for (var n=1; n<=item.length; n++) 
    test.push(item.substr(0,n) + "*" + item.substr(n+1,item.length-n)); 
    var result = []; 
    for (var r=0; r<test.length; r++) for (var i=0; i<arr.length; i++) { 
    if (arr[i].toLowerCase().indexOf(test[r].toLowerCase().split("*")[0]) != -1) 
    if (arr[i].toLowerCase().indexOf(test[r].toLowerCase().split("*")[1]) != -1) 
    if (0 < arr[i].toLowerCase().indexOf(test[r].toLowerCase().split("*")[1]) 
      - arr[i].toLowerCase().indexOf(test[r].toLowerCase().split("*")[0] < 2)) 
    if (!(arr[i] in oc(result))) result.push(arr[i]); 
    } 
    return result; 
} 
+1

Tại sao bạn gọi 'arr [i] .toLowerCase(). IndexOf (test [ r] .toLowerCase(). split ("*") ' hơn và hơn? – Metalstorm

20

tôi đang tìm kiếm "tìm kiếm mờ" trong javascript nhưng thiên đường' t tìm thấy một giải pháp ở đây, vì vậy tôi đã viết chức năng của riêng tôi mà làm những gì tôi cần.

Các thuật toán rất đơn giản: lặp qua chữ kim và kiểm tra xem chúng xảy ra theo thứ tự trong đống cỏ khô:

String.prototype.fuzzy = function (s) { 
    var hay = this.toLowerCase(), i = 0, n = -1, l; 
    s = s.toLowerCase(); 
    for (; l = s[i++] ;) if (!~(n = hay.indexOf(l, n + 1))) return false; 
    return true; 
}; 

ví dụ:

('a haystack with a needle').fuzzy('hay sucks'); // false 
('a haystack with a needle').fuzzy('sack hand'); // true 
+1

này phải là câu trả lời được chấp nhận! –

0

Tôi wasn không hài lòng với list.js, vì vậy tôi đã tạo của riêng mình. Đây có lẽ không phải là tìm kiếm mờ, nhưng tôi không biết phải gọi nó là gì. Tôi chỉ muốn nó khớp với một truy vấn mà không quan tâm đến thứ tự các từ của tôi trong truy vấn.

Hãy xem xét kịch bản sau đây:

  • một tập hợp các bài viết trong bộ nhớ tồn tại
  • trật tự các từ truy vấn xuất hiện không quan trọng (ví dụ"Hello world" vs "Thế giới hello")
  • Mã nên thể dễ dàng đọc được

Dưới đây là một ví dụ:

var articles = [{ 
    title: '2014 Javascript MVC Frameworks Comparison', 
    author: 'Guybrush Treepwood' 
}, { 
    title: 'Javascript in the year 2014', 
    author: 'Herman Toothrot' 
}, 
{ 
    title: 'Javascript in the year 2013', 
    author: 'Rapp Scallion' 
}]; 

var fuzzy = function(items, key) { 
    // Returns a method that you can use to create your own reusable fuzzy search. 

    return function(query) { 
    var words = query.toLowerCase().split(' '); 

    return items.filter(function(item) { 
     var normalizedTerm = item[key].toLowerCase(); 

     return words.every(function(word) { 
     return (normalizedTerm.indexOf(word) > -1); 
     }); 
    }); 
    }; 
}; 


var searchByTitle = fuzzy(articles, 'title'); 

searchByTitle('javascript 2014') // returns the 1st and 2nd items 

Vâng, tôi hy vọng điều này sẽ giúp người ra khỏi đó.

1

Giải pháp khác (đơn giản). Không phân biệt chữ hoa chữ thường và bỏ qua thứ tự các chữ cái.

Nó thực hiện kiểm tra mọi chữ cái của cụm từ tìm kiếm. Nếu chuỗi gốc chứa chữ cái đó, nó sẽ đếm lên (hoặc xuống nếu không). Dựa trên tỷ lệ của các trận đấu/chuỗi độ dài nó sẽ trả về true hoặc false.

String.prototype.fuzzy = function(term, ratio) { 
    var string = this.toLowerCase(); 
    var compare = term.toLowerCase(); 
    var matches = 0; 
    if (string.indexOf(compare) > -1) return true; // covers basic partial matches 
    for (var i = 0; i < compare.length; i++) { 
     string.indexOf(compare[i]) > -1 ? matches += 1 : matches -=1; 
    } 
    return (matches/this.length >= ratio || term == "") 
}; 

Ví dụ:

("Test").fuzzy("st", 0.5) // returns true 
("Test").fuzzy("tes", 0.8) // returns false cause ratio is too low (0.75) 
("Test").fuzzy("stet", 1) // returns true 
("Test").fuzzy("zzzzzest", 0.75) // returns false cause too many alien characters ("z") 
("Test").fuzzy("es", 1) // returns true cause partial match (despite ratio being only 0.5)