Ricerca…


Sintassi

  • mentre cond; corpo; fine
  • rompere
  • Continua

Osservazioni

Il ciclo while non ha un valore; sebbene possa essere usato nella posizione dell'espressione, il suo tipo è Void e il valore ottenuto non sarà nothing .

Sequenza di Collatz

Il ciclo while esegue il suo corpo finché dura la condizione. Ad esempio, il codice seguente calcola e stampa la sequenza Collatz da un numero dato:

function collatz(n)
    while n ≠ 1
        println(n)
        n = iseven(n) ? n ÷ 2 : 3n + 1
    end
    println("1... and 4, 2, 1, 4, 2, 1 and so on")
end

Uso:

julia> collatz(10)
10
5
16
8
4
2
1... and 4, 2, 1, 4, 2, 1 and so on

È possibile scrivere qualsiasi ciclo in modo ricorsivo, e per cicli complessi while volte la variante ricorsiva è più chiara. Tuttavia, in Julia, i loop presentano alcuni vantaggi distinti rispetto alla ricorsione:

  • Julia non garantisce l'eliminazione delle chiamate tail, pertanto la ricorsione utilizza memoria aggiuntiva e può causare errori di overflow dello stack.
  • Inoltre, per lo stesso motivo, un loop può avere un sovraccarico e correre più velocemente.

Esegui una volta prima di testare la condizione

A volte, si vuole eseguire un codice di inizializzazione una volta prima di testare una condizione. In certi altri linguaggi, questo tipo di loop ha una sintassi speciale do - while . Tuttavia, questa sintassi può essere sostituita con una normale istruzione while loop e break , quindi Julia non ha una sintassi specialistica do - while . Invece, si scrive:

local name

# continue asking for input until satisfied
while true
    # read user input
    println("Type your name, without lowercase letters:")
    name = readline()

    # if there are no lowercase letters, we have our result!
    !any(islower, name) && break
end

Si noti che in alcune situazioni, tali cicli potrebbero essere più chiari con la ricorsione:

function getname()
    println("Type your name, without lowercase letters:")
    name = readline()
    if any(islower, name)
        getname()  # this name is unacceptable; try again
    else
        name       # this name is good, return it
    end
end

Ricerca per ampiezza

0.5.0

(Sebbene questo esempio sia scritto usando la sintassi introdotta nella versione v0.5, può funzionare anche con alcune modifiche su versioni precedenti).

Questa implementazione della ricerca in ampiezza (BFS) su un grafico rappresentato con elenchi di adiacenza utilizza i cicli while e l'istruzione return . Il compito che risolveremo è il seguente: abbiamo una sequenza di persone e una sequenza di amicizie (le amicizie sono reciproche). Vogliamo determinare il grado di connessione tra due persone. Cioè, se due persone sono amici, restituiremo 1 ; se uno è amico di un amico dell'altro, restituiremo 2 , e così via.

Innanzitutto, supponiamo di avere già un elenco di adiacenze: un Dict mappa T to Array{T, 1} , dove le chiavi sono persone ei valori sono tutti gli amici di quella persona. Qui possiamo rappresentare le persone con qualsiasi tipo T scegliamo; in questo esempio, useremo Symbol . Nell'algoritmo BFS, manteniamo una coda di persone da "visitare" e contrassegniamo la loro distanza dal nodo di origine.

function degree(adjlist, source, dest)
    distances = Dict(source => 0)
    queue = [source]

    # until the queue is empty, get elements and inspect their neighbours
    while !isempty(queue)
        # shift the first element off the queue
        current = shift!(queue)

        # base case: if this is the destination, just return the distance
        if current == dest
            return distances[dest]
        end

        # go through all the neighbours
        for neighbour in adjlist[current]
            # if their distance is not already known...
            if !haskey(distances, neighbour)
                # then set the distance
                distances[neighbour] = distances[current] + 1

                # and put into queue for later inspection
                push!(queue, neighbour)
            end
        end
    end

    # we could not find a valid path
    error("$source and $dest are not connected.")
end

Ora, scriveremo una funzione per costruire una lista di adiacenze data una sequenza di persone e una sequenza di tuple (person, person) :

function makeadjlist(people, friendships)
    # dictionary comprehension (with generator expression)
    result = Dict(p => eltype(people)[] for p in people)

    # deconstructing for; friendship is mutual
    for (a, b) in friendships
        push!(result[a], b)
        push!(result[b], a)
    end

    result
end

Ora possiamo definire la funzione originale:

degree(people, friendships, source, dest) =
    degree(makeadjlist(people, friendships), source, dest)

Ora testiamo la nostra funzione su alcuni dati.

const people = [:jean, :javert, :cosette, :gavroche, :éponine, :marius]
const friendships = [
    (:jean, :cosette),
    (:jean, :marius),
    (:cosette, :éponine),
    (:cosette, :marius),
    (:gavroche, :éponine)
]

Jean è collegato a se stesso in 0 passaggi:

julia> degree(people, friendships, :jean, :jean)
0

Jean e Cosette sono amici, e così hanno il grado 1 :

julia> degree(people, friendships, :jean, :cosette)
1

Jean e Gavroche sono collegati indirettamente attraverso Cosette e poi Marius, quindi la loro laurea è 3 :

julia> degree(people, friendships, :jean, :gavroche)
3

Javert e Marius non sono collegati attraverso alcuna catena, quindi viene generato un errore:

julia> degree(people, friendships, :javert, :marius)
ERROR: javert and marius are not connected.
 in degree(::Dict{Symbol,Array{Symbol,1}}, ::Symbol, ::Symbol) at ./REPL[28]:27
 in degree(::Array{Symbol,1}, ::Array{Tuple{Symbol,Symbol},1}, ::Symbol, ::Symbol) at ./REPL[30]:1


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow