2012-04-04 16 views
5

Pracuję nad aplikacją internetową, która zawiera długie listy nazwisk. Klient początkowo chciał, aby nazwy dzieliły się na litery div s za pomocą liter, więc łatwo jest przeskoczyć do określonej nazwy na liście.Listing alfabetycznie, grupy listów z kilkoma wpisami razem (PHP lub JS)

Teraz, patrząc na listę, klient wskazał kilka liter, które mają tylko jedną lub dwie nazwy skojarzone z nimi. Teraz chce wiedzieć, czy możemy połączyć kilka kolejnych liter, jeśli w każdym z nich jest tylko kilka nazwisk.

(Zauważ, że litery bez nazwy nie są wyświetlane w ogóle.)

Co mam teraz zrobić, to mieć serwer bazy danych zwróci listę sortowane, a następnie zachować zmienną zawierającą obecną postać. Przeglądam listę nazw, zwiększając liczbę znaków i drukując znaczniki otwierające i zamykające, tak jak pojawia się każda litera. Wiem, jak zaadaptować ten kod, aby połączyć kilka liter, ale jedyną rzeczą, której nie jestem pewien, jak sobie poradzić, jest to, czy konkretna kombinacja liter jest najlepsza z możliwych. Innymi słowy, że mam:

  • A - 12 Nazwy
  • B - 2 nazwach
  • C - 1 Nazwa
  • D - 1 Nazwa
  • E - 1 Nazwa
  • F - 23 nazwy

Wiem, jak skończyć z grupą A-C, a następnie samemu D. To, czego szukam, to: wydajny sposób, aby zdać sobie sprawę, że A powinno być samo w sobie, a następnie B-D powinny być razem.

Nie jestem pewien, od czego zacząć.

Jeśli ma to znaczenie, ten kod zostanie użyty w module Kohana Framework.


UPDATE 2012-04-04:

Oto wyjaśnienie, czego potrzebuję:

Say minimalna liczba elementów Chcę w grupie wynosi 30. Teraz mówią, że litera A ma 25 pozycji, litery B, C i D, każdy ma po 10 pozycji, a litera E ma 32 pozycje. Chcę zostawić A samemu, ponieważ lepiej będzie połączyć B + C + D. Prostym sposobem na ich połączenie jest A + B, C + D + E - czego nie chcę.

Innymi słowy, potrzebuję najlepszego dopasowania, które jest najbliżej minimum w grupie.

+1

Oto skrzypce z wyjściowej listy nazwisk, jeśli ludzie chcą zrobić kilka testów z metody js. http://jsfiddle.net/Avveb/ – mrtsherman

+0

Wiem, że można to zrobić za pomocą dużego programowania dynamicznego, ale mam nadzieję, że ktoś znajdzie coś na tyle prostego, aby można go było użyć w aplikacji sieciowej. Jeśli potrzebuję korzystać z programowania dynamicznego, będę musiał uruchomić je od czasu do czasu i zapisać wyniki w pamięci podręcznej, ponieważ będzie to zbyt intensywne, aby można było je uruchomić po wczytaniu strony. –

Odpowiedz

1

Jeśli list zawiera więcej niż 10 nazw lub jakikolwiek rozsądny limit, który ustawisz, nie łącz go z następnym. Jednakże, jeśli zaczniesz łączyć litery, możesz uruchomić je do momentu, gdy 15 lub więcej nazw zostanie zebranych, jeśli chcesz, o ile żadna pojedyncza litera nie będzie miała więcej niż 10. To nie jest uniwersalne rozwiązanie, ale właśnie w ten sposób go rozwiązam.

+0

Prawdopodobnie to właśnie zrobię. Niestety, nie jest to coś, co miałem nadzieję zrobić. –

0

Używanie jsfiddle że mrsherman put, wymyśliłem coś, co mogłoby działać: http://jsfiddle.net/F2Ahh/

Oczywiście, że ma być używany jako Pseudokod, niektóre techniki, aby uczynić go bardziej efektywne mogą być stosowane. Ale to robi zadanie.

+0

To nie robi tego, co chcę. Mam już kod, który może je tak rozbić, wystarczy dodać następną grupę, jeśli ta grupa jest mniejsza niż min. Zobacz moją aktualizację pytania. –

1

Wpadłem na tę funkcję za pomocą PHP. Grupuje litery, które mają łącznie ponad $ nazwy amount.

function split_by_initials($names,$ammount,$tollerance = 0) { 
    $total = count($names); 
    foreach($names as $name) { 
     $filtered[$name[0]][] = $name; 
    } 
    $count = 0; 
    $key = ''; 
    $temp = array(); 
    foreach ($filtered as $initial => $split) { 
     $count += count($split); 
     $temp = array_merge($split,$temp); 
     $key .= $initial.'-'; 
     if ($count >= $ammount || $count >= $ammount - $tollerance) { 
      $result[$key] = $temp; 
      $count = 0; 
      $key = ''; 
      $temp = array(); 
     } 
    } 
    return $result; 
} 

3rd parametr jest używany, gdy chcesz ograniczyć grupę, do jednej litery, które nie podano ammount ale jest wystarczająco blisko.

Coś chcę podzielić w grupach po 30 ale ma 25 na tak, jeśli ustawisz tollerance 5, A będzie zostawić w spokoju, a pozostałe litery będą grupowane.

Zapomniałem wspomnieć, ale zwraca tablicę wielowymiarową z literami, które zawiera jako klucz, a następnie nazwy, które zawiera. Coś

 
Array 
(
    [A-B-C-] => Array 
     (
      [0] => Bandice Bergen 
      [1] => Arey Lowell 
      [2] => Carmen Miranda 
     ) 
) 

To nie jest dokładnie to, co potrzebne, ale myślę, że to wystarczająco blisko.

0

Javascrip Wersja: udoskonalona wersja z sortowania i grupowania symboli

function group_by_initials(names,ammount,tollerance) { 
     tolerance=tollerance||0; 
     total = names.length; 
     var filtered={} 
     var result={}; 
     $.each(names,function(key,value){ 
      val=value.trim(); 
      var pattern = /[a-zA-Z0-9&_\.-]/ 
      if(val[0].match(pattern)) { 
       intial=val[0]; 
      } 
      else 
      { 
       intial='sym'; 
      } 
      if(!(intial in filtered)) 
       filtered[intial]=[]; 

      filtered[intial].push(val); 
     }) 
     var count = 0; 
     var key = ''; 
     var temp = []; 
     $.each(Object.keys(filtered).sort(),function(ky,value){ 
      count += filtered[value].length; 
      temp = temp.concat(filtered[value]) 
      key += value+'-'; 
      if (count >= ammount || count >= ammount - tollerance) { 
       key = key.substring(0, key.length - 1); 
       result[key] = temp; 
       count = 0; 
       key = ''; 
       temp = []; 
      } 
     }) 
     return result; 
    }