Сумма родовых: Пособие при рождении ребенка в 2023 году \ КонсультантПлюс

Общие расширения sum() и mean() для числовых коллекций Swift · GitHub

/// Чтобы использовать метод reduce() для суммирования последовательности, нам нужно
///
/// — нулевой (идентификационный) элемент
/// — оператор сложения
Протокол Суммируемый {
/// Элемент идентификации для этого типа и операции +.
статическая переменная Zero: Self {get}
/// Для этого типа должен быть определен оператор +
func +(lhs: Self, rhs: Self) -> Self
}
расширение SequenceType, где Generator. Element: Summable {
/// Возвращаем сумму всех значений в последовательности
func sum() -> Generator.Element {
вернуть self.reduce(Generator.Element.Zero, объединить: +)
}
}
// Определить ноль для Int, Double и String, чтобы мы могли их sum().
//
// Распространите это на любые другие типы, для которых вы хотите использовать sum().
расширение Int: суммируемое {
/// Значение Int 0
статическая переменная Ноль: Int { return 0 }
}
расширение Двойное: суммируемое {
/// Двойное значение 0.0
статическая переменная Zero: Double {return 0.0}
}
Строка расширения: суммируемая {
/// Пустая строка
статическая переменная Zero: String { return «» }
}
/// Общая функция mean() требует, чтобы мы могли
/// для преобразования значений в Double.
Протокол
DoubleConvertible {
/// Возвращаемое значение типа Double
var doubleValue: Double {получить}
}
// Определить doubleValue() для Int и Double.
//
// Расширьте это на любые другие типы, для которых вы хотите
// для использования среднего().
расширение Int: DoubleConvertible {
/// Вернуть Int как Double
var doubleValue: Double { return Double(self) }
}
удлинитель Double: DoubleConvertible {
/// Возвращаем двойное значение
var doubleValue: Double { return self }
}
расширение CollectionType, где
Генератор. Элемент: DoubleConvertible,
Генератор.Элемент: Суммируемый,
Index.Distance: DoubleConvertible {
/// Возвращаем среднее арифметическое значений в коллекции
функция означает() -> Двойной {
assert(!self.isEmpty, «невозможно вычислить среднее значение пустой коллекции»)
возврат self.sum().doubleValue / self.count.doubleValue
}
}
// Примеры
[1, 2, 3, 4, 5]. sum() // 15
[1.1, 2.2, 3.3, 4.4, 5.5].sum() // 16.5
[«a», «b», «c», «d», «e»].sum() // «abcde»
[1, 2, 3, 5].среднее() // 2,75
[0,4, 1,2, 3,2].среднее() // 1,6

Учебное пособие. Начало работы с универсальными шаблонами

В этом учебном пособии представлены основы универсальных шаблонов в Go. С помощью дженериков вы можете объявлять и использовать функции или типы, которые написаны для работы с любым набором типов, предоставляемых вызывающим кодом.

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

Вы пройдете следующие разделы:

  1. Создайте папку для своего кода.
  2. Добавить необобщенные функции.
  3. Добавьте общую функцию для обработки нескольких типов.
  4. Удалить аргументы типа при вызове универсальной функции.
  5. Объявите ограничение типа.

Примечание: Другие учебные пособия см. в разделе Учебные пособия.

Примечание: При желании вы можете использовать игровая площадка Go в режиме «Go dev branch» вместо этого редактировать и запускать вашу программу.

Предпосылки

  • Установка Go 1.18 или более поздней версии. Инструкции по установке см. Установка Го.
  • Инструмент для редактирования вашего кода. Любой текстовый редактор, который у вас есть, будет работать нормально.
  • Командный терминал. Go хорошо работает с любым терминалом на Linux и Mac, и на PowerShell или cmd в Windows.

Создайте папку для вашего кода

Для начала создайте папку для кода, который вы будете писать.

  1. Откройте командную строку и перейдите в свой домашний каталог.

    В Linux или Mac:

    $ кд
     

    В Windows:

     C:\> компакт-диск %HOMEPATH%
     

    В остальной части руководства в качестве подсказки будет отображаться символ $. Команды, которые вы используете будет работать и в Windows.

  2. В командной строке создайте каталог для своего кода с именем generics.

     $ mkdir дженерики
    $ cd дженерики
     
  3. Создайте модуль для хранения вашего кода.

    Запустите команду go mod init , указав путь к модулю вашего нового кода.

     $ go mod init пример/дженерики
    go: создание нового go.mod: пример модуля/дженерики
     

    Примечание. Для производственного кода следует указать более конкретный путь к модулю. к вашим собственным потребностям. Чтобы узнать больше, обязательно посмотрите Управление зависимостями.

Далее вы добавите простой код для работы с картами.

Добавить необобщенные функции

На этом шаге вы добавите две функции, каждая из которых суммирует значения карту и вернуть общее количество.

Вы объявляете две функции вместо одной, потому что работаете с двумя различные типы карт: одна, которая хранит значения int64 , и одна, которая хранит значения float64 .

Напишите код
  1. С помощью текстового редактора создайте файл с именем main.go в универсальных каталог. Вы будете писать свой код Go в этом файле.

  2. В файл main.go в верхней части файла вставьте следующий пакет декларация.

     пакет основной
     

    Автономная программа (в отличие от библиотеки) всегда находится в пакете main .

  3. Под объявлением пакета вставьте следующие две функции декларации.

     // SumInts суммирует значения m.
    func SumInts(m map[string]int64) int64 {
        переменная int64
        для _, v := диапазон m {
            с += v
        }
        вернуть с
    }
    // SumFloats суммирует значения m.
    func SumFloats(m map[string]float64) float64 {
        переменная с плавающей запятой64
        для _, v := диапазон m {
            с += v
        }
        вернуть с
    }
     

    В этом коде вы:

    • Объявить две функции для сложения значений карты и возврата сумма.
      • SumFloats преобразует строки в значения float64 .
      • SumInts выполняет сопоставление строк с значениями int64 .
  4. В верхней части main.go под объявлением пакета вставьте следующее основная функция для инициализации двух карт и использования их в качестве аргументов при вызов функций, которые вы объявили на предыдущем шаге.

     функция main () {
        // Инициализировать карту для целочисленных значений
        целые числа: = карта [строка] int64 {
            «первая»: 34,
            "второй": 12,
        }
        // Инициализируем карту для значений с плавающей запятой
        поплавки: = карта [строка] float64 {
            «первый»: 35,98,
            «секунда»: 26,99,
        }
        fmt. Printf("Необщие суммы: %v и %v\n",
            SumInts(целые),
            SumFloats(плавает))
    }
     

    В этом коде вы:

    • Инициализировать карту из значений float64 и карту из int64 значений, каждое с двумя входами.
    • Вызовите две объявленные ранее функции, чтобы найти сумму каждой из них. значения карты.
    • Распечатать результат.
  5. В верхней части main.go, прямо под объявлением пакета, импортируйте package, который вам понадобится для поддержки кода, который вы только что написали.

    Первые строки кода должны выглядеть так:

     пакет основной
    импортировать "фмт"
     
  6. Сохранить main.go.

Запустите код

Из командной строки в каталоге, содержащем main.go, запустите код.

$ беги.
Необщие суммы: 46 и 62,97.
 

С помощью дженериков здесь можно написать одну функцию вместо двух. Далее вы будете добавьте одну общую функцию для карт, содержащих либо целочисленные значения, либо значения с плавающей запятой.

Добавьте общую функцию для обработки нескольких типов

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

Для поддержки значений любого типа этой единственной функции потребуется способ объявить, какие типы он поддерживает. С другой стороны, для вызова кода потребуется способ указать, вызывается ли он с целочисленной или плавающей картой.

Для поддержки этого вы напишете функцию, которая объявляет параметры типа в в дополнение к своим обычным параметрам функции. Эти параметры типа делают универсальная функция, позволяющая ей работать с аргументами разных типов. Вы будете вызвать функцию с 9Аргументы типа 0654 и обычные аргументы функций.

Каждый параметр типа имеет ограничение типа , которое действует как своего рода метатип для параметра типа. Каждое ограничение типа указывает допустимый тип аргументы, которые вызывающий код может использовать для соответствующего параметра типа.

Хотя ограничение параметра типа обычно представляет собой набор типов, в во время компиляции параметр типа обозначает один тип — предоставленный тип в качестве аргумента типа вызывающим кодом. Если тип аргумента типа не допускается ограничением параметра типа, код не будет компилироваться.

Имейте в виду, что параметр типа должен поддерживать все операции универсального код выполняется на нем. Например, если код вашей функции пытается выполнить строковых операций (таких как индексация) над параметром типа, чей ограничение включало числовые типы, код не компилировался.

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

Напишите код
  1. Под двумя функциями, которые вы добавили ранее, вставьте следующий общий функция.

     // SumIntsOrFloats суммирует значения карты m. Он поддерживает как int64, так и float64.
    // как типы для значений карты.
    func SumIntsOrFloats[K сопоставимый, V int64 | float64](m map[K]V) V {
        вар с V
        для _, v := диапазон m {
            с += v
        }
        вернуть с
    }
     

    В этом коде вы:

    • Объявите функцию SumIntsOrFloats с двумя параметрами типа (внутри квадратные скобки), K и V , и один аргумент, использующий тип параметры, м типа карта[К]В . Функция возвращает значение тип В .
    • Укажите для параметра типа K ограничение типа , сравнимое с . Предназначенное специально для таких случаев, ограничение , сопоставимое с . предварительно объявлено в Go. Он позволяет использовать любой тип, значения которого могут использоваться в качестве операнд операторов сравнения == и != . Go требует эту карту ключи сопоставимы. Таким образом, объявление K как аналогичный необходим так что вы можно использовать K в качестве ключа в переменной карты. Это также гарантирует, что вызов код использует допустимый тип для ключей карты.
    • Укажите для параметра типа V ограничение, которое представляет собой объединение двух типы: int64 и float64 . Использование | указывает объединение двух типы, что означает, что это ограничение допускает любой тип. Любой тип будет разрешено компилятором в качестве аргумента в вызывающем коде.
    • Укажите, что аргумент m имеет тип map[K]V , где K и V являются типами, уже указанными для параметров типа. Обратите внимание, что мы know map[K]V является допустимым типом карты, поскольку K является сопоставимым типом. Если мы не объявили K сопоставимыми, компилятор отклонил бы ссылка на карту [K]V .
  2. В main.go под уже имеющимся кодом вставьте следующий код.

     fmt.Printf("Общие суммы: %v и %v\n",
        SumIntsOrFloats[строка, int64](целые),
        SumIntsOrFloats[строка, float64](плавает))
     

    В этом коде вы:

    • Вызов только что объявленной универсальной функции, передавая каждую из карт вы создали.

    • Укажите аргументы типа — имена типов в квадратных скобках — которые ясно о типах, которые должны заменить параметры типа в функция, которую вы вызываете.

      Как вы увидите в следующем разделе, часто можно опустить тип аргументы в вызове функции. Go часто может вывести их из вашего кода.

    • Вывести суммы, возвращаемые функцией.

Запустите код

Из командной строки в каталоге, содержащем main.go, запустите код.

$ беги.
Необщие суммы: 46 и 62,97.
Общие суммы: 46 и 62,97
 

Чтобы запустить ваш код, в каждом вызове компилятор заменял параметры типа на конкретные типы, указанные в этом вызове.

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

Удалить аргументы типа при вызове универсальной функции

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

Вы можете опустить аргументы типа в вызывающем коде, если компилятор Go может вывести типы, которые вы хотите использовать. Компилятор выводит аргументы типа из типов аргументы функции.

Обратите внимание, что это не всегда возможно. Например, если вам нужно позвонить универсальная функция без аргументов, вам нужно будет включить тип аргументы в вызове функции.

Напишите код
  • В main. go под уже имеющимся кодом вставьте следующий код.

     fmt.Printf("Общие суммы, выведенные параметры типа: %v и %v\n",
        SumIntsOrFloats(целые),
        SumIntsOrFloats(плавает))
     

    В этом коде вы:

    • Вызов универсальной функции без аргументов типа.
Запустите код

Из командной строки в каталоге, содержащем main.go, запустите код.

$ беги.
Необщие суммы: 46 и 62,97.
Общие суммы: 46 и 62,97
Общие суммы, предполагаемые параметры типа: 46 и 62,97
 

Далее вы еще больше упростите функцию, захватив объединение целых чисел и плавает в ограничение типа, которое вы можете повторно использовать, например, из другого кода.

Объявить ограничение типа

В этом последнем разделе вы переместите ограничение, которое вы определили ранее, в его собственный интерфейс, чтобы вы могли повторно использовать его в нескольких местах. Объявление ограничения таким образом помогают упростить код, например, когда ограничение более сложный.

Вы объявляете ограничение типа как интерфейс. Ограничение позволяет любое тип, реализующий интерфейс. Например, если вы объявляете ограничение типа интерфейс с тремя методами, затем используйте его с параметром типа в универсальном функции, аргументы типа, используемые для вызова функции, должны иметь все эти методы.

Интерфейсы ограничений также могут ссылаться на определенные типы, как вы увидите в этом раздел.

Напишите код
  1. Чуть выше main , сразу после операторов импорта вставьте следующий код для объявления ограничения типа.

     тип Номер интерфейса {
        интервал64 | поплавок64
    }
     

    В этом коде вы:

    • Объявите тип интерфейса Number для использования в качестве ограничения типа.

    • Объявить объединение int64 и float64 внутри интерфейса.

      По сути, вы перемещаете объединение из объявления функции в ограничение нового типа. Таким образом, когда вы хотите ограничить тип параметр либо int64 или float64 , вы можете использовать этот номер ограничение типа вместо записи int64 | поплавок64 .

  2. Под уже имеющимися функциями вставьте следующий общий Функция SumNumbers .

     // SumNumbers суммирует значения карты m. Он поддерживает оба целых числа
    // и плавает как значения карты.
    func SumNumbers[K сопоставимый, V Number](m map[K]V) V {
        вар с V
        для _, v := диапазон m {
            с += v
        }
        вернуть с
    }
     

    В этом коде вы:

    • Объявите универсальную функцию с той же логикой, что и универсальная функция вы объявили ранее, но с новым типом интерфейса вместо union как ограничение типа. Как и раньше, вы используете параметры типа для типов аргументов и возвращаемых значений.
  3. В main.go под уже имеющимся кодом вставьте следующий код.

     fmt. Printf("Общие суммы с ограничением: %v и %v\n",
        СуммаЧисла (целые),
        СуммаЧисла(с плавающей запятой))
     

    В этом коде вы:

    • Вызов SumNumbers с каждой картой, печать суммы из значений каждый.

      Как и в предыдущем разделе, вы опускаете аргументы типа (тип имена в квадратных скобках) при вызовах универсальной функции. Идти компилятор может вывести аргумент типа из других аргументов.

Запустите код

Из командной строки в каталоге, содержащем main.go, запустите код.

$ беги .
Необщие суммы: 46 и 62,97.
Общие суммы: 46 и 62,97
Общие суммы, предполагаемые параметры типа: 46 и 62,97
Общие суммы с ограничением: 46 и 62,97
 

Заключение

Отлично сделано! Вы только что познакомились с дженериками в Go.

Предлагаемые следующие темы:

  • Go Tour — отличная пошаговая введение в основы Go.
  • Вы найдете полезные передовые практики Go, описанные в Эффективное движение и Как написать код на Go.

Завершенный код

Вы можете запустить эту программу в Иди на детскую площадку. На площадка просто нажмите кнопку Run .

 пакет основной
импортировать "фмт"
тип числовой интерфейс {
 интервал64 | поплавок64
}
основная функция () {
 // Инициализировать карту для целочисленных значений
 целые числа: = карта [строка] int64 {
 «первая»: 34,
 "второй": 12,
 }
 // Инициализируем карту для значений с плавающей запятой
 поплавки: = карта [строка] float64 {
 «первый»: 35,98,
 «второй»: 26,99,
 }
 fmt.Printf("Необщие суммы: %v и %v\n",
 SumInts(целые),
 SumFloats(плавает))
 fmt.Printf("Общие суммы: %v и %v\n",
 SumIntsOrFloats[строка, int64](целые),
 SumIntsOrFloats[строка, float64](плавает))
 fmt.Printf("Общие суммы, выведенные параметры типа: %v и %v\n",
 SumIntsOrFloats(целые),
 SumIntsOrFloats(плавает))
 fmt.Printf("Общие суммы с ограничением: %v и %v\n",
 СуммаЧисла (целые),
 СуммаЧисла(с плавающей запятой))
}
// SumInts суммирует значения m.

Оставьте комментарий