Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sort a list and exchange elements

sort() orders a list in place without allocating. Tuples sort by their first component, so sorting (start, stop) spans puts overlapping spans next to each other. Merging them is then one pass:

def merge(spans: &mut list[(i64, i64)]) -> Result[list[(i64, i64)], AllocError]:
    spans.sort()
    mut merged: list[(i64, i64)] = []?
    for i in range(len(spans)):
        start, stop = spans[i]
        if len(merged) > 0 and start <= merged[-1][1]:
            if stop > merged[-1][1]:
                merged[-1] = (merged[-1][0], stop)
        else:
            merged.append((start, stop))?
    Ok(merged)

def main() -> Result[(), AllocError | IoError]:
    mut spans = [(8, 10), (1, 3), (15, 18), (2, 6)]?
    print(merge(&mut spans)?)?
    print(spans)?
    Ok(())
[(1, 6), (8, 10), (15, 18)]
[(1, 3), (2, 6), (8, 10), (15, 18)]

swap(i, j) exchanges two elements of any type in place. Here it moves the row with the largest leading value to the top, as elimination with pivoting does, without copying a row:

def pivot(rows: &mut list[list[i64]]) -> ():
    mut best = 0
    for i in range(1, len(rows)):
        if rows[i][0] > rows[best][0]:
            best = i
    rows.swap(0, best)

def main() -> Result[(), AllocError | IoError]:
    mut rows = [[1, 2]?, [7, 8]?, [4, 5]?]?
    pivot(&mut rows)
    print(rows)?
    Ok(())
[[7, 8], [1, 2], [4, 5]]

Copyable elements can also be exchanged by assigning several targets: items[i], items[j] = items[j], items[i].