Поиск…


Синтаксис

  • в то время как cond; тело; конец
  • перерыв
  • Продолжить

замечания

В while цикл не имеет значения; хотя его можно использовать в позиции выражения, его тип - Void и полученное значение будет nothing .

Последовательность Collatz

В while цикл выполняется его тело, пока имеет место условие. Например, следующий код вычисляет и печатает последовательность Collatz с заданного числа:

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

Использование:

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

Можно написать любой цикл рекурсивно, так и для комплекса , while петли, иногда рекурсивный вариант более ясно. Однако в Julia циклы имеют определенные преимущества перед рекурсией:

  • Julia не гарантирует устранения хвостового вызова, поэтому рекурсия использует дополнительную память и может вызвать ошибки переполнения стека.
  • И далее, по той же причине, цикл может уменьшиться накладные расходы и работать быстрее.

Запуск один раз перед тестированием

Иногда перед запуском какого-либо условия требуется запустить некоторый код инициализации. В некоторых других языках этот вид цикла имеет специальный синтаксис do while . Тем не менее, этот синтаксис может быть заменен постоянным во while цикла и break заявление, поэтому Джулия не специализировалась do - в while синтаксис. Вместо этого вы пишете:

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

Обратите внимание, что в некоторых ситуациях такие циклы могут быть более ясными с рекурсией:

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

Поиск по ширине

0.5.0

(Хотя этот пример написан с использованием синтаксиса, представленного в версии v0.5, он может работать и с небольшими изменениями в старых версиях.)

Эта реализация поиска по ширине (BFS) на графике, представленном списками смежности, использует циклы while и оператор return . Задача, которую мы решаем, заключается в следующем: у нас есть последовательность людей, и последовательность дружеских отношений (дружба взаимна). Мы хотим определить степень связи между двумя людьми. То есть, если два человека являются друзьями, мы вернем 1 ; если кто-то друг друга другого, мы вернем 2 и т. д.

Сначала предположим, что у нас уже есть список смежности: Dict отображающий T в Array{T, 1} , где ключи - это люди, а значения - все друзья этого человека. Здесь мы можем представлять людей с любым типом T мы выбираем; в этом примере мы будем использовать Symbol . В алгоритме BFS мы сохраняем очередь людей для «посещения» и отмечаем их расстояние от узла происхождения.

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

Теперь мы напишем функцию для построения списка смежности с учетом последовательности людей и последовательности (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

Теперь мы можем определить исходную функцию:

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

Теперь давайте проверим нашу функцию на некоторых данных.

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

Жан связан с собой в 0 шагах:

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

Джин и Козетт - друзья, и у них есть степень 1 :

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

Жан и Гаврох связаны косвенно через Косет, а затем Мариус, поэтому их степень составляет 3 :

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

Javert и Marius не связаны ни с одной цепью, поэтому возникает ошибка:

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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow