2014-06-27 13 views
10

documentation mówi, że Set.head zwraca "pierwszy" element, a .tail zwraca "wszystkie oprócz pierwszego". * Ponieważ Set tak naprawdę nie ma "pierwszego" elementu, dokumentacja ostrzega, że ​​bez zamówionego typu, możesz uzyskać inny wynik w różnych seriach. Ale czy masz gwarancję, że ogon nie będzie zawierał głowy?Czy głowa i ogon zestawu gwarantują wzajemną wyłączność?

Powodem Pytam się zastanawiam, czy to OK rekursja dół Set takiego:

def recurse(itemsToExamine: Set[Item], acc: Result): Result = 
    if (itemsToExamine.isEmpty) acc 
    else { 
    val item = itemsToExamine.head 
    recurse(
     item.spawnMoreItems ++ itemsToExamine.tail, 
     acc.updatedFor(item)) 
    } 

Jeśli to uzasadnione, z pewnością byłoby ładniej niż konwersja z Set do Seq iz powrotem w celu oddzielenia głowy i ogona na każdej rekursji.


* W rzeczywistości komunikat "wybiera pierwszy element" i "wybiera wszystkie oprócz pierwszego elementu". Zakładam, że "wybiera" to po prostu kiepski wybór słów. Jeśli istnieje powód, by powiedzieć "wybiera" zamiast "zwraca", proszę dać mi znać.

Odpowiedz

4

nie jestem 100% pewna, bo nie wyglądał zbyt dużo w realizacji, ale dla każdego HashSet istnieje niejawna zamawiania oparty na hashCode (typu Int) z wartościami, które są już w Set.

Oznacza to, że w przypadku każdej instancji połączenia z numerami head i tail będą respektować tę kolejność, więc nie będzie to ten sam element. Co więcej, kolejna iteracja poprzez elementy danej instancji Set powinna przynieść elementy w tej samej kolejności, ponieważ Set jest niezmienna.

Na wynos jest to, że podczas zamawiania jest nieznany, istnieje jeden dla każdej instancji, która może ulec zmianie, jak tylko dodać (zmiennie lub niezmiennie) nowy element do Set.

4

Poleganie na head i tail na Set (bez zamawiania) jest w najlepszym wypadku ryzykowne.

W twoim przypadku po prostu uzyskaj Iterator z twojego Set najpierw z theSet.toIterator, a następnie powróć do iteratora. Iterator gwarantuje oczywiście, że pierwszy element będzie inny od pozostałych.

+1

Co to jest odpowiednik '.tail' dla' Iterator'? '.toSet' po wywołaniu' .next'? –

3

Można to zrobić:

val set = Set(1, 2, 3) 
val head = set.head 
val tail = set - head 

To jest gwarantowane, aby utrzymać je wzajemnie się wykluczają.