Операции со списками

Освойте операции со списками и коллекциями в Топазе. Изучите продвинутые техники манипулирования массивами, картами, множествами и всеми типами коллекций.

Топаз предоставляет мощные операции со списками и коллекциями для эффективной работы со структурами данных. Все операции поддерживают неизменность и функциональное программирование. 📊

📋 Операции с массивами

Создание и инициализация массивов

// Различные способы создания массивов
let пустойМассив: Array<int> = []
let массивЧисел = [1, 2, 3, 4, 5]
let массивСтрок = ["яблоко", "банан", "вишня"]

// Создание массивов с повторением
let повторяющийсяМассив = Array.fill(10, 0)              // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
let массивДиапазона = Array.range(1, 6)                  // [1, 2, 3, 4, 5]
let сгенерированныйМассив = Array.generate(5, i => i * 2) // [0, 2, 4, 6, 8]

// Вывод типов и дженерики
let смешанныйМассив: Array<any> = [1, "привет", true]
let дженерикМассив: Array<T> = Array.new()

print("Массив чисел: {массивЧисел}")
print("Массив диапазона: {массивДиапазона}")
print("Сгенерированный массив: {сгенерированныйМассив}")

Операции преобразования массивов

let исходныйМассив = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// map - преобразование каждого элемента
let массивКвадратов = исходныйМассив.map=> х * х)
let массивСтрок = исходныйМассив.map=> "Число: {х}")
let массивОбъектов = исходныйМассив.map=> { значение: х, квадрат: х * х })

// flatMap - объединение выравнивания и отображения
let вложенныйМассив = [[1, 2], [3, 4], [5, 6]]
let выровненный = вложенныйМассив.flatMap(масс => масс)     // [1, 2, 3, 4, 5, 6]

// Условное отображение
let условноеПреобразование = исходныйМассив.map=> {
    if х % 2 == 0 {
        return х * 2
    } else {
        return х
    }
})

print("Массив квадратов: {массивКвадратов}")
print("Выровненный: {выровненный}")
print("Условное преобразование: {условноеПреобразование}")

Операции фильтрации массивов

let тестовыйМассив = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

// Базовая фильтрация
let фильтрЧётных = тестовыйМассив.filter=> х % 2 == 0)     // [2, 4, 6, 8, 10, 12, 14]
let фильтрБольших = тестовыйМассив.filter=> х > 10)        // [11, 12, 13, 14, 15]

// Фильтрация по сложным условиям
let сложныйФильтр = тестовыйМассив.filter=> х % 2 == 0 && х > 5)  // [6, 8, 10, 12, 14]

// Фильтрация по индексу
let индексныйФильтр = тестовыйМассив.filterWithIndex((значение, индекс) => индекс % 3 == 0)

// Типовая фильтрация
let смешанныеДанные: Array<any> = [1, "привет", 3.14, true, "мир", 42]
let толькоЧисла = смешанныеДанные.filter=> match х {
    case _: int => true
    case _: float => true
    case _ => false
})     // [1, 3.14, 42]
let толькоСтроки = смешанныеДанные.filter=> match х {
    case _: string => true
    case _ => false
})     // ["привет", "мир"]

print("Фильтр чётных: {фильтрЧётных}")
print("Сложный фильтр: {сложныйФильтр}")
print("Только числа: {толькоЧисла}")

Операции накопления массивов

let числа = [1, 2, 3, 4, 5]

// reduce - базовое накопление
let сумма = числа.reduce((накопл, текущ) => накопл + текущ, 0)        // 15
let произведение = числа.reduce((накопл, текущ) => накопл * текущ, 1)    // 120
let максимум = числа.reduce((накопл, текущ) => Math.max(накопл, текущ), числа[0])

// reduceRight - накопление справа
let правоеНакопление = числа.reduceRight((накопл, текущ) => накопл + текущ, 0)

// scan - включить промежуточные результаты
let накопительнаяСумма = числа.scan((накопл, текущ) => накопл + текущ, 0)     // [0, 1, 3, 6, 10, 15]

// Сложная операция накопления
let статистика = числа.reduce((накопл, текущ) => {
    return {
        сумма: накопл.сумма + текущ,
        количество: накопл.количество + 1,
        максимум: Math.max(накопл.максимум, текущ),
        минимум: Math.min(накопл.минимум, текущ)
    }
}, { сумма: 0, количество: 0, максимум: -Infinity, минимум: Infinity })

print("Сумма: {сумма}")
print("Накопительная сумма: {накопительнаяСумма}")
print("Статистика: {статистика}")

🔍 Поиск и сортировка массивов

Операции поиска

let массивДанных = [10, 25, 8, 15, 32, 7, 18, 42, 3, 29]

// Базовый поиск
let найдено = массивДанных.find=> х > 20)              // Some(25)
let найденИндекс = массивДанных.findIndex=> х > 20)    // Some(1)
let найденоПоследнее = массивДанных.findLast=> х > 20)      // Some(42)

// Множественный поиск
let всеБольшие = массивДанных.filter=> х > 20)         // [25, 32, 42, 29]
let первыеТри = массивДанных.take(3)                      // [10, 25, 8]
let последниеТри = массивДанных.takeLast(3)               // [42, 3, 29]

// Условный поиск
let условныйПоиск = массивДанных.takeWhile=> х != 32)     // [10, 25, 8, 15]
let условныйПропуск = массивДанных.skipWhile=> х < 20)       // [25, 8, 15, 32, 7, 18, 42, 3, 29]

// Бинарный поиск (на отсортированном массиве)
let отсортированныйМассив = [1, 3, 5, 7, 9, 11, 13, 15]
let результатБинарногоПоиска = отсортированныйМассив.binarySearch(9)          // Some(4)

print("Найдено: {найдено}")
print("Все большие: {всеБольшие}")
print("Условный поиск: {условныйПоиск}")

Операции сортировки

let случайныйМассив = [64, 34, 25, 12, 22, 11, 90, 5]

// Базовая сортировка
let поВозрастанию = случайныйМассив.sort()                      // [5, 11, 12, 22, 25, 34, 64, 90]
let поУбыванию = случайныйМассив.sortDescending()               // [90, 64, 34, 25, 22, 12, 11, 5]

// Пользовательская сортировка
let пользовательскаяСортировка = случайныйМассив.sortBy((а, б) => {
    if а % 2 == 0 && б % 2 != 0 { return -1 }    // Чётные числа первыми
    if а % 2 != 0 && б % 2 == 0 { return 1 }     // Нечётные числа последними
    return а - б                                   // Одинаковый тип по возрастанию
})

// Сортировка массива объектов
let пользователи = [
    { имя: "Иван", возраст: 25, оценка: 85 },
    { имя: "Алиса", возраст: 30, оценка: 92 },
    { имя: "Боб", возраст: 20, оценка: 78 }
]

let отсортированноПоВозрасту = пользователи.sortBy(пользователь => пользователь.возраст)
let отсортированноПоОценке = пользователи.sortByDescending(пользователь => пользователь.оценка)
let множественнаяСортировка = пользователи.sortBy([
    пользователь => пользователь.оценка,      // 1-й: оценка по возрастанию
    пользователь => -пользователь.возраст     // 2-й: возраст по убыванию
])

print("Пользовательская сортировка: {пользовательскаяСортировка}")
print("Отсортировано по возрасту: {отсортированноПоВозрасту}")
print("Отсортировано по оценке: {отсортированноПоОценке}")

📊 Операции с множествами

Создание множеств и базовые операции

// Создание множеств
let пустоеМножество: Set<int> = Set.new()
let множествоЧисел = Set.from([1, 2, 3, 4, 5])
let дедуплицированноеМножество = Set.from([1, 1, 2, 2, 3, 3])    // {1, 2, 3}

// Базовые операции с множествами
let mut изменяемоеМножество = Set.from([1, 2, 3])
изменяемоеМножество.add(4)                                      // {1, 2, 3, 4}
изменяемоеМножество.remove(2)                                   // {1, 3, 4}

let проверкаСодержания = изменяемоеМножество.contains(3)             // true
let размер = изменяемоеМножество.size()                           // 3

// Преобразование множества
let вМассив = изменяемоеМножество.toArray()                     // [1, 3, 4]
let вСписок = изменяемоеМножество.toList()                       // List(1, 3, 4)

print("Множество чисел: {множествоЧисел}")
print("Изменяемое множество: {изменяемоеМножество}")

Математические операции с множествами

let множествоА = Set.from([1, 2, 3, 4, 5])
let множествоБ = Set.from([4, 5, 6, 7, 8])
let множествоВ = Set.from([1, 3, 5, 7, 9])

// Объединение
let объединение = множествоА.union(множествоБ)                     // {1, 2, 3, 4, 5, 6, 7, 8}

// Пересечение
let пересечение = множествоА.intersection(множествоБ)              // {4, 5}

// Разность
let разность = множествоА.difference(множествоБ)                   // {1, 2, 3}

// Симметричная разность
let симметричнаяРазность = множествоА.symmetricDifference(множествоБ)   // {1, 2, 3, 6, 7, 8}

// Проверка подмножества
let подмножество = Set.from([1, 2]).isSubsetOf(множествоА)    // true
let надмножество = множествоА.isSupersetOf(Set.from([1, 2]))  // true

// Проверка пересечения
let пересекается = множествоА.intersects(множествоБ)            // true

print("Объединение: {объединение}")
print("Пересечение: {пересечение}")
print("Разность: {разность}")
print("Симметричная разность: {симметричнаяРазность}")

🗺️ Операции с картами

Создание карт и базовые операции

// Создание карт
let пустаяКарта: Map<string, int> = Map.new()
let картаОценок = Map.from([
    ["Иван", 85],
    ["Алиса", 92],
    ["Боб", 78]
])

// Базовые операции с картами
let mut изменяемаяКарта = Map.new()
изменяемаяКарта.set("яблоко", 1000)
изменяемаяКарта.set("банан", 1500)
изменяемаяКарта.set("апельсин", 2000)

let получитьЗначение = изменяемаяКарта.get("яблоко")                 // Some(1000)
let естьКлюч = изменяемаяКарта.has("банан")                  // true
let проверкаРазмера = изменяемаяКарта.size()                      // 3

// Получить со значением по умолчанию
let значениеПоУмолчанию = изменяемаяКарта.getOrDefault("виноград", 0)         // 0

// Итерация по карте
изменяемаяКарта.forEach((значение, ключ) => {
    print("{ключ}: {значение}")
})

print("Карта оценок: {картаОценок}")
print("Изменяемая карта: {изменяемаяКарта}")

Преобразование и фильтрация карт

let картаТоваров = Map.from([
    ["ноутбук", 1500000],
    ["мышь", 50000],
    ["клавиатура", 120000],
    ["монитор", 300000],
    ["колонка", 80000]
])

// Преобразование карты
let ценыСоСкидкой = картаТоваров.map((цена, товар) => цена * 0.9)
let описанияТоваров = картаТоваров.map((цена, товар) => "{товар}: {цена}")

// Фильтрация карты
let дорогиеТовары = картаТоваров.filter((цена, товар) => цена > 100000)
let конкретныеТовары = картаТоваров.filterKeys(товар => товар.contains("бук"))

// Извлечение ключей и значений
let всеКлючи = картаТоваров.keys()                        // ["ноутбук", "мышь", ...]
let всеЗначения = картаТоваров.values()                    // [1500000, 50000, ...]
let записи = картаТоваров.entries()                     // [["ноутбук", 1500000], ...]

// Слияние карт
let дополнительныеТовары = Map.from([["планшет", 800000], ["зарядка", 30000]])
let объединённаяКарта = картаТоваров.merge(дополнительныеТовары)

print("Цены со скидкой: {ценыСоСкидкой}")
print("Дорогие товары: {дорогиеТовары}")
print("Все ключи: {всеКлючи}")

📝 Продвинутые операции со списками

Функциональные операции со списками

let списокЧисел = List.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

// Цепочечные операции
let результатСложнойОперации = списокЧисел
    .filter=> х % 2 == 0)        // Только чётные числа
    .map=> х * х)                // Квадрат
    .take(3)                        // Первые 3
    .sum()                          // Сумма

// Операции разбиения
let (чётные, нечётные) = списокЧисел.partition=> х % 2 == 0)
let группировкаПоОстатку = списокЧисел.groupBy=> х % 3)    // Группировка по остатку

// Оконные операции (скользящее окно)
let окно3 = списокЧисел.windowed(3)              // [[1,2,3], [2,3,4], [3,4,5], ...]
let кусок2 = списокЧисел.chunked(2)                // [[1,2], [3,4], [5,6], [7,8], [9,10]]

// zip операции
let списокСимволов = List.from(["а", "б", "в", "г", "д"])
let результатЗапаковки = списокЧисел.zip(списокСимволов)       // [(1,"а"), (2,"б"), (3,"в"), (4,"г"), (5,"д")]

print("Результат сложной операции: {результатСложнойОперации}")
print("Чётные: {чётные}, Нечётные: {нечётные}")
print("Окно 3: {окно3}")
print("Результат запаковки: {результатЗапаковки}")

Операции агрегации списков

let списокОценок = List.from([85, 92, 78, 96, 84, 88, 79, 91])

// Базовая агрегация
let общаяСумма = списокОценок.sum()                       // 693
let среднее = списокОценок.average()                 // 86.625
let максимальное = списокОценок.max()                     // Some(96)
let минимальное = списокОценок.min()                     // Some(78)
let количество = списокОценок.count()                     // 8

// Условная агрегация
let количествоВысокихОценок = списокОценок.count=> х >= 90)  // 3
let суммаВысокихОценок = списокОценок.sumBy=> if х >= 90 { х } else { 0 })

// Статистические вычисления
let дисперсия = списокОценок.variance()
let стандартноеОтклонение = списокОценок.standardDeviation()
let медиана = списокОценок.median()

// Пользовательская агрегация
let пользовательскаяАгрегация = списокОценок.aggregate(
    начальное: { сумма: 0, количество: 0, наивысшая: 0 },
    функция: (накопл, текущая) => {
        return {
            сумма: накопл.сумма + текущая,
            количество: накопл.количество + 1,
            наивысшая: Math.max(накопл.наивысшая, текущая)
        }
    }
)

print("Среднее: {среднее}")
print("Стандартное отклонение: {стандартноеОтклонение}")
print("Пользовательская агрегация: {пользовательскаяАгрегация}")

🔄 Операции преобразования коллекций

Преобразование между коллекциями

// Преобразование Массив ↔ Список ↔ Множество
let исходныйМассив = [1, 2, 2, 3, 3, 4, 5]
let преобразованиеВСписок = List.from(исходныйМассив)
let преобразованиеВМножество = Set.from(исходныйМассив)          // Дубликаты удалены
let обратноВМассив = преобразованиеВМножество.toArray()

// Преобразование в карту
let парыКлючЗначение = [["а", 1], ["б", 2], ["в", 3]]
let преобразованиеВКарту = Map.from(парыКлючЗначение)

// Преобразование группировки
let оценкиСтудентов = [
    { имя: "Иван", предмет: "Математика", оценка: 85 },
    { имя: "Иван", предмет: "Английский", оценка: 90 },
    { имя: "Алиса", предмет: "Математика", оценка: 95 },
    { имя: "Алиса", предмет: "Английский", оценка: 88 }
]

let группировкаПоСтуденту = оценкиСтудентов.groupBy=> х.имя)
let группировкаПоПредмету = оценкиСтудентов.groupBy=> х.предмет)

// Индексация карты
let индексПоИмени = оценкиСтудентов.associateBy=> х.имя)
let отображениеКлючЗначение = оценкиСтудентов.associate=>.имя, х.оценка])

print("Преобразование в множество: {преобразованиеВМножество}")
print("Группировка по студенту: {группировкаПоСтуденту}")
print("Индекс по имени: {индексПоИмени}")

⚡ Операции оптимизации производительности

Ленивое вычисление

// Последовательность ленивого вычисления
let большойМассив = Array.range(1, 1000000)

// Жадное вычисление (высокое использование памяти)
let жадныйРезультат = большойМассив
    .filter=> х % 2 == 0)
    .map=> х * х)
    .take(10)

// Ленивое вычисление (эффективное использование памяти)
let лениваяПоследовательность = большойМассив
    .asSequence()
    .filter=> х % 2 == 0)
    .map=> х * х)
    .take(10)
    .toList()

// Бесконечная последовательность
let последовательностьФибоначчи = Sequence.generate(
    начальное: [0, 1],
    генератор: ([а, б]) => [б, а + б]
).map(([а, б]) => а)

let первыеДесятьФибоначчи = последовательностьФибоначчи.take(10).toList()

print("Результат ленивой последовательности: {лениваяПоследовательность}")
print("Первые десять Фибоначчи: {первыеДесятьФибоначчи}")

Параллельная обработка

// Большие данные, подходящие для параллельной обработки
let большиеДанные = Array.range(1, 100000)

// Последовательная обработка
let последовательныйРезультат = большиеДанные
    .filter=> простоеЧисло(х))
    .sum()

// Параллельная обработка
let параллельныйРезультат = большиеДанные
    .parallel()
    .filter=> простоеЧисло(х))
    .sum()

// Функция проверки простого числа
function простоеЧисло(н: int) -> bool {
    if н < 2 { return false }
    for и in 2..Math.sqrt(н) {
        if н % и == 0 { return false }
    }
    return true
}

// Параллельное map-reduce
let параллельноеМапРедьюс = большиеДанные
    .parallel()
    .map=> х * х)
    .reduce((а, б) => а + б, 0)

print("Параллельный результат: {параллельныйРезультат}")

🛠️ Пользовательские коллекции

Реализация пользовательской коллекции

// Реализация стека
struct Стек<T> {
    элементы: Array<T>
}

impl<T> Стек<T> {
    function new() -> Стек<T> {
        return Стек { элементы: [] }
    }
    
    function push(элемент: T) {
        self.элементы.push(элемент)
    }
    
    function pop() -> Option<T> {
        return self.элементы.pop()
    }
    
    function peek() -> Option<T> {
        return self.элементы.last()
    }
    
    function isEmpty() -> bool {
        return self.элементы.isEmpty()
    }
    
    function size() -> int {
        return self.элементы.length()
    }
    
    // Реализация итератора
    function iterator() -> Iterator<T> {
        return self.элементы.reverse().iterator()
    }
}

// Пример использования
let mut стек = Стек.new()
стек.push(1)
стек.push(2)
стек.push(3)

let верхний = стек.peek()                      // Some(3)
let извлечённый = стек.pop()                    // Some(3)

for элемент in стек {
    print("Элемент стека: {элемент}")
}

print("Верхний: {верхний}")
print("Извлечённый: {извлечённый}")

Специализированные операции коллекций

// Очередь с приоритетом
let очередьПриоритетов = PriorityQueue.new((а, б) => а - б)  // Минимальная куча
очередьПриоритетов.enqueue(5)
очередьПриоритетов.enqueue(2)
очередьПриоритетов.enqueue(8)
очередьПриоритетов.enqueue(1)

while !очередьПриоритетов.isEmpty() {
    let минимальное = очередьПриоритетов.dequeue()
    print("Приоритет: {минимальное}")                // Порядок 1, 2, 5, 8
}

// TreeMap (отсортированная карта)
let деревоКарта = TreeMap.new()
деревоКарта.put("в", 3)
деревоКарта.put("а", 1)
деревоКарта.put("б", 2)

// Вывод в отсортированном порядке
for (ключ, значение) in деревоКарта {
    print("{ключ}: {значение}")                      // Порядок а:1, б:2, в:3
}

// MultiMap (несколько значений на ключ)
let мультиКарта = MultiMap.new()
мультиКарта.put("фрукты", "яблоко")
мультиКарта.put("фрукты", "банан")
мультиКарта.put("овощи", "морковь")

let фрукты = мультиКарта.get("фрукты")               // ["яблоко", "банан"]

print("Фрукты: {фрукты}")

Операции со списками Топаз делают обработку данных эффективной и выразительной. Используйте неизменность и функциональное программирование для написания безопасного и читаемого кода! 🎯