Привет, друзья!
Я — JavaScript-разработчик
. Код пишу в основном на React
(иногда на Vue
), немного на TypeScript
, немного на Node
, немного знаю SQL
, но...
- со мной работает много людей, которые пишут код на
Python
- вокруг много разговоров про
Python
- повсюду преподают
Python
- Яндекс любит
Python
(раньше Гугл тоже его любил, но теперь у него естьGo
)
Короче говоря, сложно было не заинтересоваться Python
.
Как известно, лучший способ научиться "кодить" — это писать код.
Предлагаю вашему вниманию 50
популярных в сфере программирования задач, решенных с помощью Python
и JavaScript
.
Цель — сравнить языки на предмет предоставляемых ими возможностей.
Задачки не очень сложные, хотя имеется парочка из категории продвинутых.
Предполагается, что вы владеете хотя бы одним из названных языков на среднем уровне.
Я старался комментировать ключевые моменты. Однако, это не гайд по JavaScript
или Python
, поэтому за подробностями работы той или иной функции или метода вам придется обращаться к другим источникам (в конце концов, что это за разработчик, который не умеет гуглить).
Если вы найдете более оптимальное или эффективное с точки зрения производительности решение, поделитесь им в комментариях или пришлите мне в личку, я обязательно добавлю его в список. Единственное условие — решение должно быть не просто другим, а лучшим по объективным причинам.
Я старался выбирать задачи, которые, во-первых, можно без особого труда (т.е. без "плясок с бубном") решить на обоих языках, во-вторых, можно решить аналогичным или хотя бы похожим образом. Отчасти поэтому некоторые решения могут выглядеть нетипичными для того или иного языка. Это опять же обусловлено сравнением между функционалом и конструкциями JavaScript
и Python
.
Приветствуются любые конструктивные замечания и предложения.
Список задач:
- 1. Вывести сообщение "Hello world!"
- 2. Сложить два числа
- 3. Извлечь квадратный корень из числа
- 4. Вычислить площадь треугольника
- 5. Произвести обмен значениями между переменными
- 6. Функция для получения случайного целого числа в заданном диапазоне
- 7. Функция для преобразования километров в мили
- 8. Функция для преобразования градусов Цельсия в градусы Фаренгейта
- 9. Функция для определения того, каким является число: положительным, отрицательным или нулем
- 10. Функция для определения того, каким является число, четным или нечетным
- 11. Функция для определения того, является ли год високосным
- 12. Функция для определения наибольшего числа
- 13. Функция для определения того, является ли число простым
- 14. Функция для вывода всех простых чисел в заданном диапазоне
- 15. Функция для вычисления факториала числа
- 16. Функция для вывода таблицы умножения для указанного числа
- 17. Функция для вычисления суммы чисел из последовательности Фибоначчи до указанного
- 18. Функция для вычисления суммы натуральных чисел от 1 до указанного
- 19. Функция для вывода чисел в степени 2 от 1 до указанного
- 20. Функция для определения всех чисел, которые делятся на другое число без остатка
- 21. Функция для вычисления наибольшего общего делителя
- 22. Функция для вычисления наименьшего общего кратного
- 23. Функция для определения всех чисел, на которые без остатка делится указанное
- 24. Простой калькулятор
- 25. Функция для преобразования числа в двоичное представление
- 26. Функция для сложения матриц
- 27. Функция для транспонирования матрицы
- 28. Функция для определения того, является ли строка палиндромом
- 29. Функция для удаления лишних символов из строки
- 30. Функция для сортировки слов в алфавитном порядке
- 30. Функция для определения количества гласных в строке
- 31. Функция для рисования пирамиды
- 32. Объединить два словаря (объекта) в один
- 33. Преобразовать вложенный список (массив) в одноуровневый (плоский)
- 34. Копировать список (массив) (сделать его срез)
- 35. Перебрать ключи и значения словаря (объекта)
- 36. Отсортировать словарь (объект) по ключам и значениям
- 37. Определить, является ли список (массив) пустым
- 38. Объединить два списка (массива) в один
- 39. Извлечь подстроку из строки
- 40. Функция для получения случайного элемента массива
- 41. Определить количество вхождений элемента в массиве
- 42. Объединить два списка (массива) в словарь (объект)
- 43. Удалить лишние пробелы из строки с помощью регулярного выражения
- 44. Создать перечисления (enum)
- 45. Функция для определения анаграмм
- 46. "Капитализировать" строку
- 47. Функция для определения всех вариантов строки
- 48. Создание счетчика (таймера)
- 49. Создание вложенной директории
- 50. Получение названий файлов с расширением ".txt"
1. Вывести сообщение "Hello world!"
Python
print('Hello world!')
JavaScript
console.log('Hello world!')
// или
alert('Hello world!')
Фраза "Hello world" переводится не как "Привет, мир", а как "Привет всем" или, если быть более аутентичным, "Привет, народ". Вы знали об этом?
2. Сложить два числа
Python
# переменные для чисел
num1 = 2
num2 = 4
# num1, num2 = 2, 4 - так делать можно, но не рекомендуется
# переменная для суммы
sum = num1 + num2
# f-строки позволяют интерполировать переменные
print(f'{num1} + {num2} = {sum}') # 2 + 4 = 6
JavaScript
const num1 = 4
const num2 = 2
// const num1 = 4, num2 = 2 - так делать можно, но не рекомендуется
const sum = num1 + num2
// для интерполяции переменных в `JS` используются шаблонные или строковые литералы
console.log(`${num1} + ${num2} = ${sum}`) // 2 + 4 = 6
3. Извлечь квадратный корень из числа
Python
num = 4
# получаем 2.0
sqrt = num ** 0.5
# встроенная функция `int()` преобразует число в целое
print(f'Квадратным корнем {num} является {int(sqrt)}')
# Квадратным корнем 4 являет
# для выполнения математических операций в `Python`
# имеется специальный модуль
from math import sqrt
print(sqrt(4)) # 2.0
JavaScript
const num = 4
// получаем 2, поэтому необходимость в округлении числа до целого отсутствует
const sqrt = num ** 0.5
console.log(`Квадратным корнем ${num} является ${sqrt}`)
// для выполнения математических операций в `JS`
// имеется глобальный объект
console.log(Math.sqrt(4)) // 2
4. Вычислить площадь треугольника
Здесь можно почитать про различные способы вычисления площади треугольника.
Если a
, b
и c
— три стороны треугольника, то согласно формуле Герона для того, чтобы вычислить площадь треугольника,
- сначала необходимо вычислить разность полупериметра и каждой его стороны
- затем найти произведение полученных чисел, умножить результат на полупериметр и найти корень из полученного числа
p = (a + b + c) / 2
s = √(p * (p - a) * (p - b) * (p - c))
p
— это полупериметр, а s
— площадь.
Python
a = 5
b = 6
c = 7
# вычисляем полупериметр
p = (a + b + c) / 2
# вычисляем площадь
s = (p * (p - a) * (p - b) * (p - c)) ** 0.5
# `round(num, count)` используется для округления числа в ближайшую сторону
# `count` - количество цифр после запятой
print(f'Площадь треугольника со сторонами {a}, {b} и {c} равняется {round(s, 2)}')
JavaScript
const a = 5
const b = 6
const c = 7
const p = (a + b + c) / 2
const s = (p * (p - a) * (p - b) * (p - c)) ** 0.5
// в `JS` метод `Math.round()` округляет число до целого в ближайшуй сторону,
// поэтому мы используем метод `toFixed(count)`
console.log(`Площадь треугольника со сторонами ${a}, ${b} и ${c} равняется ${s.toFixed(2)}`)
5. Произвести обмен значениями между переменными
Python
x = 5
y = 10
# с помощью дополнительной (временной) переменной
t = x
x = y
y = t
# такой трюк в `JS` провернуть нельзя,
# но там есть другой
x, y = y, x
# с помощью сложения и вычитания
x = x + y
y = x - y
x = x - y
# c помощью умножения и деления
x = x * y
y = x / y
x = x / y
# с помощью исключающего ИЛИ (XOR)
x = x ^ y
y = x ^ y
x = x ^ y
JavaScript
// в целом, все то же самое, за исключением следующего:
// переменные должны объявляться с помощью ключевого слова `let`,
// чтобы они были мутабельными (изменяемыми)
// в `Python` по умолчанию все переменные являются мутабельными
let x = 5
let y = 10
let t = x
x = y
y = t
// трюк на `JS`
// обратите внимание на ; перед [
;[x, y] = [y, x]
// с помощью сложения и вычитания
// c помощью умножения и деления
// с помощью исключающего ИЛИ (XOR)
6. Функция для получения случайного целого числа в заданном диапазоне
Python
В Python
для этого существует специальный модуль:
# импортируем метод из модуля
from random import randint
# такая функция называется лямбдой
get_random_int = lambda min, max: randint(min, max)
print(f'Случайное целое число в диапазоне от 0 до 100: {get_random_int(0, 100)}')
JavaScript
В JS
готовой функции для этого нет, поэтому придется реализовать ее самостоятельно:
// такая функция называется стрелочной
// ~~ - это сокращение для `Math.floor()` - округление числа до целого в меньшую сторону
// `Math.random()` возвращает случайное число от 0 до 1
const getRandomInt = (min, max) => ~~(min + Math.random() * (max - min + 1))
console.log(`Случайное целое число в диапазоне от 0 до 100: ${getRandomInt(0, 100)}`)
7. Функция для преобразования километров в мили
Python
# запрашиваем км у "юзера" с помощью `input()`
# `float()` преобразует строку в число с запятой
km = float(input('Введите значение в км: '))
# фактор преобразования
f = 0.621371
# вычисляем мили
m = km * f
# km = m / f
print(f'{km} километров - это {round(m, 2)} миль')
JavaScript
// запрашиваем км у юзера с помощью `prompt()`
// `Number()` преобразует строку в число
const km = Number(prompt('Введите значение в км: '))
const f = 0.621371
const m = km * f
alert(`${km} километров - это ${m.toFixed(2)} миль`)
8. Функция для преобразования градусов Цельсия в градусы Фаренгейта
Python
# запрашиваем градусы Цельсия у юзера
c = float(input('Введите значение в градусах Цельсия: '))
# преобразуем Цельсий в Фаренгейт
f = (c * 1.8) + 32
# c = (f - 32) / 1.8
print(f'{c} градусов Цельсия - это {round(f, 2)} градусов Фаренгейта')
JavaScript
// запрашиваем градусы Цельсия у юзера
const c = Number(prompt('Введите значение в градусах Цельсия: '))
const f = c * 1.8 + 32
alert(`${c} градусов Цельсия - это ${f.toFixed(2)} градусов Фаренгейта`)
9. Функция для определения того, каким является число: положительным, отрицательным или нулем
Python
# сигнатура обычной функции
# отступы имеют принципиальное значение,
# обозначая блоки кода
def is_pos_neg(n):
# если
if n > 0:
return 'Positive'
# иначе если
elif n == 0:
return 'Null'
# иначе
else:
return 'Negative'
print(
is_pos_neg(
# преобразуем строку в число c запятой
float(
input('Number: ')
)
)
)
JavaScript
// сигнатура обычной функции
// фигурные скобки имеют принципиальное значение,
// обозначая блоки кода
function isPosNeg(n) {
// если
if (n > 0) {
return 'Positive'
// иначе если
} else if (n === 0) {
return 'Null'
// иначе
} else {
return 'Negative'
}
}
alert(
isPosNeg(
// `+` (унарный префиксный плюс) - это сокращение для `Number()`
+prompt('Number: ')
)
)
10. Функция для определения того, каким является число, четным или нечетным
Python
# это называется коротким вычислением
# истина if условие else ложь
is_odd_even = lambda n: 'Even' if n % 2 == 0 else 'Odd'
print(
is_odd_even(
float(
input('Number: ')
)
)
)
JavaScript
// тернарный оператор
// условие ? истина : ложь
// обратите внимание, что в `JS` имеется 2 оператора равенства
// старайтесь всегда использовать `===`
const isOddEven = (n) => (n % 2 === 0 ? 'Even' : 'Odd')
alert(
isOddEven(
prompt('Number: ')
)
)
Раз уж мы заговорили про наличие 2 операторов равенства в JS
, здесь же обращу ваше внимание на следующее:
- логическими значениями в
Python
являютсяTrue
иFalse
(с большой буквы), а вJS
—true
иfalse
- индикатором отсутствия значения в
Python
являетсяNone
, а вJS
у нас целых 3 таких индикатора —undefined
,null
иNaN
11. Функция для определения того, является ли год високосным
Високосным является год, который делится на 4
без остатка, за исключением столетий (оканчивающихся на 00
). В последнем случае год будет високосным, если делится без остатка на 400
.
Python
def is_leap_year(year):
if (year % 4) == 0:
if (year % 100) == 0:
if (year % 400) == 0:
return 'Leap'
else:
return 'Not leap'
else:
return 'Leap'
else:
return 'Not leap'
# функцию можно переписать с помощью логических операторов `and` (И), `or` (ИЛИ) и `not` (НЕ)
def is_leap_year(year):
# `\` используется для объединения нескольких строк кода
# в один блок
if (year % 4) == 0 and (year % 100) == 0 and (year % 400) == 0 \
or (year % 4) == 0 and not (year % 100) == 0:
return 'Leap'
else:
return 'Not leap'
print(
is_leap_year(
int(
input('Year: ')
)
)
)
JavaScript
function isLeapYear(year) {
if (year % 4 === 0) {
if (year % 100 === 0) {
if (year % 400 === 0) {
return 'Leap'
} else {
return 'Not leap'
}
} else {
return 'Leap'
}
} else {
return 'Not leap'
}
}
// функцию можно переписать с помощью логических операторов `&&` (И), `||` (ИЛИ) и `!` (НЕ)
// объединение нескольких строк кода в один блок
// происходит автоматически
function isLeapYear(year) {
if (
(year % 4 === 0 && year % 100 === 0 && year % 400 === 0) ||
(year % 4 === 0 && !(year % 100 === 0))
) {
return 'Leap'
} else {
return 'Not leap'
}
}
alert(
isLeapYear(
// еще одна функция для преобразования значения в целое число
// второй аргумент - система счисления (в данном случае десятичная)
parseInt(
prompt('Year: '),
10
)
)
)
12. Функция для определения наибольшего числа
Python
def get_largest_num(n1, n2, n3):
if (n1 >= n2) and (n1 >= n2):
return n1
elif (n2 >= n1) and (n2 >= n3):
return n2
else:
return n3
print(get_largest_num(1, 3, 2)) # 3
# существует встроенная функция
print(max(3, 1, 2))
JavaScript
function getLargestNum(n1, n2, n3) {
if (n1 >= n2 && n1 >= n3) {
return n1
} else if (n2 >= n1 && n2 >= n3) {
return n2
} else {
return n3
}
}
console.log(getLargestNum(1, 3, 2)) // 3
// существует встроенная функция
console.log(Math.max(3, 1, 2))
13. Функция для определения того, является ли число простым
Простым является число, которое больше 1
и делится только на себя и 1
. Простыми являются числа 2, 3, 5, 7 и т.д. А число 6
, например, таковым не является, поскольку является составным: 2 * 3 = 6
.
Python
def is_prime(n):
if n > 1:
# `range()` осуществляет перебор (итерацию) в указанном количестве
# возможные сигнатуры:
# `range(end)`
# `range(start, end)`
# `range(start, end, step)`
for i in range(2, n):
# если имеется число, на которое `n` делится без остатка
if (n % i) == 0:
return 'Not prime'
# если такого числа нет
return 'Prime'
# если число < 1
return 'Invalid'
print(
is_prime(
int(
input('Number: ')
)
)
)
JavaScript
// в `JS` не существует аналога `range()`,
// поэтому функцию придется реализовать по-другому
function isPrime(n) {
if (n > 1) {
let i = 2
// выполнять блок кода до тех пор, пока...
while (i < n) {
if (n % i === 0) {
return 'Not prime'
}
i++
}
return 'Prime'
}
return 'Invalid'
}
alert(
isPrime(
parseInt(
prompt('Number: '),
10
)
)
)
14. Функция для вывода всех простых чисел в заданном диапазоне
Python
def get_primes(min, max):
primes = []
for n in range(min, max + 1):
if n > 1:
for i in range(2, n):
if (n % i) == 0:
# оператор `break` используется для выхода из цикла
break
else:
# `append()` помещает элемент в конец списка
primes.append(n)
return primes
print(get_primes(1, 100))
JavaScript
function getPrimes(min, max) {
const primes = []
for (let i = min; i <= max; i++) {
if (i > 1) {
// индикатор того, что число является простым
let isPrime = true
for (let j = 2; j < i; j++) {
if (i % j === 0) {
isPrime = false
break
}
}
if (isPrime) {
// `push()` помещает элемент в конец массива
primes.push(i)
}
}
}
return primes
}
console.log(getPrimes(1, 100))
15. Функция для вычисления факториала числа
Факториал — это произведение всех целых чисел от 1
до указанного. Например, факториалом числа 6
является 1 * 2 * 3 * 4 * 5 * 6 = 720
. "Указанное число" должно быть положительным. В качестве небольшой оптимизации следует принять во внимание, что факториалом чисел 1 и 2 являются, соответственно, 1 и 2.
Python
def get_factorial(n):
if n < 0: return 'Invalid'
if n < 2: return n
# это называется рекурсией
# чтобы понять рекурсию, необходимо сначала понять рекурсию ;)
return n * get_factorial(n - 1)
print(get_factorial(6)) # 720
JavaScript
function getFactorial(n) {
if (n < 0) return 'Invalid'
if (n < 2) return n
return n * getFactorial(n - 1)
}
console.log(getFactorial(6)) // 720
16. Функция для вывода таблицы умножения для указанного числа
Python
def get_mult_table(n):
for i in range(1, 11):
print(f'{n} * {i} = {n * i}')
get_mult_table(9)
JavaScript
function getMultTable(n) {
for (let i = 1; i < 11; i++) {
console.log(`${n} * ${i} = ${n * i}`)
}
}
getMultTable(9)
17. Функция для вычисления суммы чисел из последовательности Фибоначчи до указанного
Последовательность Фибоначчи — это последовательность целых чисел 0, 1, 1, 2, 3, 5, 8 и т.д. Два первых числа — это 0 и 1. Последующие числа — это результат сложения двух предыдущих.
Python
# рекурсивная реализация будет гораздо менее производительной
def get_fibonacci_sum(n):
if n < 0: return 'Invalid'
if n <= 1: return n
a = 1
b = 1
for i in range(3, n + 1):
c = a + b
a = b
b = c
return b
print(get_fibonacci_sum(10)) # 55
JavaScript
function getFibonacciSum(n) {
if (n < 0) return 'Invalid'
if (n <= 1) return n
let a = 1
let b = 1
for (let i = 3; i <= n; i++) {
let c = a + b
a = b
b = c
}
return b
}
console.log(getFibonacciSum(10)) // 55
18. Функция для вычисления суммы натуральных чисел от 1 до указанного
Натуральные числа — числа, возникающие естественным образом при счете (1, 2, 3, 4, 5, 6, 7 и т.д.).
Python
def get_natural_sum(n):
if n < 0: return 'Invalid'
s = 0
while n > 0:
s += n
n -= 1
return s
print(
get_natural_sum(10)
)
# с помощью лямбда-функции
get_nat_sum = lambda n: 'Invalid' if n < 0 else int(n * (n + 1) / 2)
print(
get_nat_sum(10)
)
JavaScript
function getNaturalSum(n) {
if (n < 0) return 'Invalid'
let s = 0
while (n > 0) {
s += n
n -= 1
}
return s
}
console.log(
getNaturalSum(10)
)
// с помощью стрелочной функции
const getNatSum = (n) => n < 0 ? 'Invalid' : n * (n + 1) / 2
console.log(
getNatSum(10)
)
19. Функция для вывода чисел в степени 2 от 1 до указанного
Python
def get_power_of_2(n):
# `r` - список с результатами
# `list(iterable)` создает список
# `iterable` - итерируемая или перебираемая сущность
# `map(function, iterable)` - вызывает `function` для каждого элемента в `iterable
r = list(map(lambda x: 2 ** x, range(1, n + 1)))
for i in range(n):
# `r[i]` извлекает элемент с указанным индексом
print(f'2 ** {i + 1} = {r[i]}')
get_power_of_2(10)
JavaScript
function getPowerOf2(n) {
// `Array.from(iterable, function)` - создает массив, в том числе с помощью функции,
// вызываемой для каждого элемента массива
// `length` - длина создаваемого массива
// `function` принимает элемент и его индекс
const r = Array.from({ length: n }, (_, i) => 2 ** (i + 1))
for (const i in r) {
// `r[i]` извлекает элемент с указанным индексом
console.log(`2 ** ${+i + 1} = ${r[i]}`)
}
}
getPowerOf2(10)
20. Функция для определения всех чисел, которые делятся на другое число без остатка
Python
# создаем список, первым элементом которого является `10`, с шагом `10`, до `210`
nums = list(map(lambda x: x, range(10, 210, 10)))
# `filter(function, iterable)` выполняет фильтрацию списка
# `function` возвращает логическое значение - критерий фильтрации
div_nums = lambda n: list(filter(lambda x: (x % n) == 0, nums))
print(div_nums(6))
JavaScript
const nums = Array.from({ length: 10 }, (_, i) => i > 0 ? (i + 1) * 10 : 10)
// `filter(function)` возвращает отфильтрованный массив
const div_nums = (n) => nums.filter(_n => _n % n === 0)
console.log(div_nums(6))
21. Функция для вычисления наибольшего общего делителя
Наибольший общий делитель (он же наивысший общий фактор) — это положительное целое число, на которое без остатка делятся 2 (и более) других числа. Например, число 12
является НОД чисел 36
и 48
.
Python
def get_gcd(x, y):
# переменная для меньшего числа
s = x
if x > y: s = y
for i in range(1, s + 1):
if ((x % i == 0) and (y % i == 0)):
# в данном случае мы можем "переиспользовать" переменную `s`
s = i
return s
print(get_gcd(48, 36)) # 12
JavaScript
function getGcd(x, y) {
let s = x
if (x > y) s = y
// мы не можем переопределять переменную `s`,
// потому что используем ее в цикле
let r = 1
for (let i = 1; i <= s; i++) {
if (x % i === 0 && y % i === 0) {
r = i
}
}
return r
}
console.log(getGcd(24, 54)) // 6
22. Функция для вычисления наименьшего общего кратного
Наименьшее общее кратное — это положительное целое число, которое делится без остатка на два (и более) других числа. Например, число 84
является НОК чисел 12
и 14
.
Python
def get_lcm(x, y):
# переменная для большего числа
g = x
if x < y: g = y
# осторожно: потенциально бесконечный цикл
while True:
if (g % x == 0) and (g % y == 0):
break
g += 1
return g
print(get_lcm(12, 14)) # 84
JavaScript
function getLCM(x, y) {
let g = x
if (x < y) g = y
// осторожно: потенциально бесконечный цикл
// в данном случае мы можем переиспользовать переменную `g`
while (true) {
if (g % x === 0 && g % y === 0) {
break
}
g += 1
}
return g
}
console.log(getLCM(24, 54)) // 216
23. Функция для определения всех чисел, на которые без остатка делится указанное
Python
def get_factors(n):
f = []
for i in range(1, n + 1):
if n % i == 0:
f.append(i)
return f
print(get_factors(123)) # [1, 3, 41, 123]
JavaScript
function getFactors(n) {
const f = []
for (let i = 1; i <= n; i++) {
if (n % i === 0) {
f.push(i)
}
}
return f
}
console.log(getFactors(321)) // [1, 3, 107, 321]
24. Простой калькулятор
Почему бы не реализовать его на классах?
Python
class Calc:
# инициализация класса
def __init__(self):
# результат
self.result = 0
# метод для добавления числа
def add(self, n):
self.result += n
# возвращаем экземпляр, чтобы иметь возможность выполнять операции в цепочке
return self
# для вычитания
def sub(self, n):
self.result -= n
return self
# для умножения
def mult(self, n):
self.result *= n
return self
# для деления
def div(self, n):
self.result /= n
return self
# создаем экземпляр
calc = Calc()
# выполняем операции
calc.add(5).sub(3).mult(4).div(2)
# выводим результат
print(int(calc.result)) # 4
JavaScript
class Calc {
// инициализация класса
constructor() {
this.result = 0
}
// в `JS` `this` (`self`) явно передавать не требуется
add(n) {
this.result += n
// возвращаем экземпляр, чтобы иметь возможность выполнять операции в цепочке
return this
}
sub(n) {
this.result -= n
return this
}
mult(n) {
this.result *= n
return this
}
div(n) {
this.result /= n
return this
}
}
// создаем экземпляр
const calc = new Calc()
// выполняем операции
calc.add(5).sub(3).mult(4).div(2)
// выводим результат
console.log(calc.result) // 4
Лично я предпочитаю функциональный стиль программирования, поэтому классов в примерах больше не будет.
25. Функция для преобразования числа в двоичное представление
Такое преобразование выполняется посредством деления числа на 2
с выводом остатка в обратном порядке. Проще показать:
Python
def convert_to_binary(n):
if n < 0: return 'Invalid'
if n > 1:
# `//` - оператор деления с округлением в меньшую сторону
# рекурсия
convert_to_binary(n // 2)
# конкатенация вывода
# в `JS` такой "фичи" нет
print(n % 2, end = '')
convert_to_binary(34)
# вывод результата
print() # 100010
JavaScript
function convertToBinary(n) {
if (n < 0) return 'Invalid'
// переменная для двоичного представления
const binary = []
while (n >= 1) {
// метод `unshift()` помещает элемент в начало массива
binary.unshift(n % 2)
n = ~~(n / 2)
}
// объединяем элементы массива в строку
return binary.join('')
}
console.log(convertToBinary(34)) // 100010
// в `JS` есть встроенная функция `toString(radix)`,
// где `radix` - это система счисления
console.log((34).toString(2)) // 100010
26. Функция для сложения матриц
Матрица может быть представлена в виде вложенного списка (массива), где каждый элемент — это строка матрицы. Пример матрицы 3x2, где 3 — это количество строк, а 2 — количество столбцов:
[
[2, 4],
[6, 8],
[1, 3]
]
Доступ к первой строке матрицы x
можно получить через x[0]
, а доступ к первому элементу первой строки — через x[0][0]
.
Обратите внимание: эта задача относится к категории продвинутых. Можете пропустить ее, если читаете статью в первый раз.
Python
def add_matrices(x, y):
# результирующая матрица
result = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
]
# `len()` возвращает длину списка
# выполняем итерацию по количеству строк
for i in range(len(x)):
# выполняем итерацию по количеству столбцов
for j in range(len(x[0])):
result[i][j] = x[i][j] + y[i][j]
return result
# матрица раз
x = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# матрица два
y = [
[9, 8, 7],
[3, 2, 1],
[6, 5, 4]
]
print(add_matrices(x, y))
'''
[
[10, 10, 10],
[7, 7, 7],
[13, 13, 13]
]
'''
# данная техника называется представлением списков (list comprehension)
add_matrices_advanced = lambda x, y: [[x[i][j] + y[i][j] for j in range(len(x[0]))] for i in range(len(x))]
print(add_matrices_advanced(x, y))
JavaScript
function addMatrices(x, y) {
const result = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
]
// выполняем итерацию по количеству строк
for (const i in x) {
// выполняем итерацию по количеству столбцов
for (const j in x[0]) {
result[i][j] = x[i][j] + y[i][j]
}
}
return result
}
const x = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
const y = [
[9, 8, 7],
[3, 2, 1],
[6, 5, 4]
]
console.log(addMatrices(x, y))
/*
[
[10, 10, 10],
[7, 7, 7],
[13, 13, 13]
]
*/
// стрелочная функция
// `map(function)` вызывает `function` для каждого элемента массива
// она принимает 2 параметра: элемент и его индекс
// и возвращает новый массив
const addMatricesAdvanced = (x, y) =>
x.map((_, i) => x[i].map((_, j) => x[i][j] + y[i][j]))
console.log(addMatricesAdvanced(x, y))
27. Функция для транспонирования матрицы
Транспонированная матрица — это матрица, полученная из исходной посредством замены строк на столбцы.
Обратите внимание: эта задача относится к категории продвинутых.
Python
def transpose_matrix(x):
# мы хотим преобразовать матрицу 3x2 в матрицу 2x3
# количество строк `x` количество столбцов
result = [
[0, 0, 0],
[0, 0, 0]
]
for i in range(len(x)):
for j in range(len(x[0])):
result[j][i] = x[i][j]
return result
x = [
[1, 2],
[4, 5],
[7, 8]
]
print(transpose_matrix(x))
'''
[
[1, 4, 7],
[2, 5, 8]
]
'''
# представление списков
transpose_matrix_advanced = lambda x: [[x[j][i] for j in range(len(x))] for i in range(len(x[0]))]
print(transpose_matrix_advanced(x))
JavaScript
function transposeMatrix(x) {
const result = [
[0, 0, 0],
[0, 0, 0]
]
for (const i in x) {
for (const j in x[0]) {
result[j][i] = x[i][j]
}
}
return result
}
const x = [
[1, 2],
[4, 5],
[7, 8]
]
console.log(transposeMatrix(x))
/*
[
[1, 4, 7],
[2, 5, 8]
]
*/
// стрелочная функция
const transposeMatrixAdvanced = (x) =>
x[0].map((_, i) => x.map((_, j) => x[j][i]))
console.log(transposeMatrixAdvanced(x))
28. Функция для определения того, является ли строка палиндромом
Палиндром — это строка (слово, число и т.д.), которая читается одинаково в обоих направлениях. Примеры: "borrow or rob", "а роза упала на лапу Азора".
Python
def is_palindrome(str):
# ''.join() - объединение в строку
# str.split(' ') - преобразование строки в массив по разделителю (в данном случае - пробелу)
# ''.join(str.split(' ')) - удаление пробелов из строки
# casefold() - нечувствительность к регистру, приведение к нижнему регистру
str = ''.join(str.split(' ')).casefold()
# инверсия строки - изменение порядка следования букв на противоположный
rev = reversed(str)
# сравнение списков
return list(str) == list(rev)
print(is_palindrome('Borrow or rob')) # True
JavaScript
function isPalindrome(str) {
// `replace()` - удаление пробелов с помощью регулярного выражения
// `toLowerCase()` - приведение к нижнему регистру
str = str.replace(/\s/g, '').toLowerCase()
// `split()` - преобразование строки в массив
// `reverse()` - инверсия
// `join()` - объединение в строку
const rev = str.split('').reverse().join('')
return str === rev
}
console.log(isPalindrome('А роза упала на лапу Азора')) // true
29. Функция для удаления лишних символов из строки
Python
# лишние символы
symbols = '''!()-[]{};:'"\,<>./?@#$%^&*_~'''
def clear(str):
# переменная для строки, очищенной от лишних символов
cleared = ''
# перебираем строку по буквам
for char in str:
# если буква не является одним из лишних символов
if char not in symbols:
# добавляем ее к очищенной строке
cleared += char
return cleared
print(
clear('Привет!! - сказал он --- и вошел')
) # Привет сказал он и вошел
JavaScript
const symbols = `!()-[]{};:'"\,<>./?@#$%^&*_~`
function clear(str) {
let cleared = ''
for (const char of str) {
if (!symbols.includes(char)) cleared += char
}
return cleared
}
console.log(
clear('Привет!! - сказал он --- и вошел')
) // Привет сказал он и вошел
30. Функция для сортировки слов в алфавитном порядке
Python
def sort_words(str):
# разбиваем строку на массив слов и
# приводим каждое слово к нижнему регистру
words = [word.lower() for word in str.split()]
# сортируем слова
words.sort()
return words
print(sort_words('Остро нуждающаяся в сортировке строка'))
'''
[
'в',
'нуждающаяся',
'остро',
'сортировке',
'строка'
]
'''
JavaScript
function sortWords(str) {
// разбиваем строку на массив слов по пробелу и
// приводим каждое слово к нижнему регистру
const words = str.split(' ').map((word) => word.toLowerCase())
words.sort()
return words
}
console.log(sortWords('Остро нуждающаяся в сортировке строк'))
/*
[
'в',
'нуждающаяся',
'остро',
'сортировке',
'строка'
]
*/
30. Функция для определения количества гласных в строке
Python
# все гласные латиницы
vowels = 'aeiou'
def get_vowels_count(str):
str = str.casefold()
# `fromkeys(iterable, initialValue)`
count = {}.fromkeys(vowels, 0)
for char in str:
# если буква гласная
if char in count:
# увеличиваем значение соответствующего ключа словаря на 1
count[char] += 1
return count
str = 'Hello! How are you today?'
print(
get_vowels_count(str)
) # { 'a': 2, 'e': 2, 'i': 0, 'o': 4, 'u': 1 }
JavaScript
const vowels = 'aeiou'
function getVowelsCount(str) {
str = str.toLowerCase()
// `[...vowels]` - преобразуем строку в массив с помощью spread-оператора
// `reduce(function, initialValue)` - аккумулирует результат на основе значений массива
const count = [...vowels].reduce((a, c) => {
a[c] = 0
return a
}, {})
for (const char of str) {
if (vowels.includes(char)) {
count[char] += 1
}
}
return count
}
const str = 'Hello! How are you today?'
console.log(
getVowelsCount(str)
) // { 'a': 2, 'e': 2, 'i': 0, 'o': 4, 'u': 1 }
31. Функция для рисования пирамиды
Обратите внимание: эта задача (точнее, 3 задачи) относятся к категории продвинутых. Это последняя относительно сложная задача, дальше будет намного проще.
Половина пирамиды
Python
def draw_half_pyramid(rows):
# для каждой строки
for i in range(rows):
# рисуем `*` в количестве,
# соответствующем порядковому номеру строки
for j in range(i + 1):
# `stdout` остается открытым
print('* ', end = '')
# переход на новую строку
if (i + 1) < rows: print('\n')
draw_half_pyramid(5)
'''
*
* *
* * *
* * * *
* * * * *
'''
JavaScript
function drawHalfPyramid(rows) {
// строка со звездочками
let pyramid = ''
// для каждой строки
for (let i = 1; i <= rows; i++) {
// рисуем `*` в количестве...
for (let j = 0; j < i; j++) {
pyramid += '* '
}
// переход на новую строку
pyramid += '\n'
}
return pyramid
}
console.log(drawHalfPyramid(5))
/*
*
* *
* * *
* * * *
* * * * *
*/
Перевернутая половина пирамиды
Python
def draw_inverted_half_pyramid(rows):
# движемся в обратную сторону
for i in range(rows, 0, -1):
for j in range(0, i):
print('* ', end = '')
if i > 1: print('\n')
draw_inverted_half_pyramid(5)
'''
* * * * *
* * * *
* * *
* *
*
'''
JavaScript
function drawInvertedHalfPyramid(rows) {
let pyramid = ''
for (let i = rows; i > 0; i--) {
for (let j = 0; j < i; j++) {
pyramid += '* '
}
pyramid += '\n'
}
return pyramid
}
console.log(drawInvertedHalfPyramid(5))
/*
* * * * *
* * * *
* * *
* *
*
*/
Полная пирамида
Python
def draw_full_pyramid(rows):
k = 0
p = ''
for i in range(1, rows + 1):
for j in range(1, (rows - i) + 1):
p += ' '
while k != (2 * i - 1):
p += '# '
k += 1
if i < rows: p += '\n'
k = 0
return p
print(draw_full_pyramid(5))
'''
#
# # #
# # # # #
# # # # # # #
# # # # # # # # #
'''
JavaScript
На JS
я решу эту задачу не таким лаконичным, но более понятным способом:
function drawFullPyramid(rows) {
let levels = ''
const mid = ~~((2 * rows - 1) / 2)
for (let row = 0; row < rows; row++) {
let level = ''
for (let col = 0; col < 2 * rows - 1; col++) {
// в данном случае мы сразу формируем тот или иной уровень
// в зависимости от положения колонки -
// до или после середины
level += mid - row <= col && col <= mid + row ? '#' : ' '
}
levels += level + '\n'
}
return levels
}
console.log(drawFullPyramid(5))
/*
#
# # #
# # # # #
# # # # # # #
# # # # # # # # #
*/
32. Объединить два словаря (объекта) в один
Python
dict_1 = { 'a': 1, 'b': 2 }
dict_2 = { 'b': 3, 'c': 4 }
# совпадающие ключи перезаписываются
print(dict_1 | dict_2) # { 'a': 1, 'b': 3, 'c': 4 }
# `**` - распаковка словарей
print({ **dict_1, **dict_2 })
JavaScript
const obj1 = { a: 1, b: 2 }
const obj2 = { b: 3, c: 4 }
// совпадающие ключи перезаписываются
console.log(
Object.assign(obj1, obj2)
) // { a: 1, b: 3, c: 4 }
// `...` - распаковка объектов
console.log({ ...obj1, ...obj2 })
33. Преобразовать вложенный список (массив) в одноуровневый (плоский)
Python
my_list = [[1], [2, 3], [4, 5, 6]]
# представление списков
flat_list_1 = [n for sub in my_list for n in sub]
print(flat_list_1) # [1, 2, 3, 4, 5, 6]
# встроенная функция `sum()`
flat_list_3 = sum(my_list, [])
print(flat_list_3)
# модуль `itertools`
import itertools
flat_list_2 = list(itertools.chain(*my_list))
print(flat_list_2)
JavaScript
const myList = [[1], [2, 3], [4, 5, 6]]
// встроенный метод `flat()`
const flatList1 = myList.flat()
console.log(flatList1) // [1, 2, 3, 4, 5, 6]
// встроенный метод `reduce()`
const flatList2 = myList.reduce((a, c) => {
c.forEach((i) => a.push(i))
return a
}, [])
console.log(flatList2)
// двойная итерация
// ключевое слово `const` делает иммутабельным
// значение самой переменной, а не массива
const flatList3 = []
for (const i of myList) {
for (const j of i) {
flatList3.push(j)
}
}
console.log(flatList3)
34. Копировать список (массив) (сделать его срез)
Python
# список (list)
my_list = [1, 2, 3, 4, 5]
# сигнатура
# `[start:end:step]`
# полная копия
print(my_list[:]) # [1, 2, 3, 4, 5]
# от второго до пятого элемента
print(my_list[1:5]) # [2, 3, 4]
# через 1 элемент, начиная с первого
print(my_list[::2]) # [1, 3, 5]
# извлекаем последний элемент
# это не относится к копированию
print(my_list[-1]) # 5
JavaScript
// массив (array)
const myList = [1, 2, 3, 4, 5]
// сигнатура
// `slice(start, end)`
// данный метод не такой мощный как питоновский аналог
// полная копия
console.log(myList.slice()) // [1, 2, 3, 4, 5]
// от второго до пятого
console.log(myList.slice(1, 5)) // [2, 3, 4]
// последний элемент - хак
console.log(...myList.slice(-1)) // 5
// последний элемент - не хак
console.log(myList[myList.length - 1])
// последний элемент - скоро, в `Chrome` уже работает
console.log(myList.at(-1)) // 5
35. Перебрать ключи и значения словаря (объекта)
Python
# словарь (dictionary)
dict = { 1: 'a', 2: 'b', 3: 'c' }
# ключи и значения
for key in dict:
print(key, dict[key])
'''
1 a
2 b
3 c
'''
# еще ключи и значения
for key, val in dict.items():
print(key, val)
# или
for key, val in dict.iteritems():
print(key, val)
# ключи
for key in dict.keys():
print(key)
# значения
for val in dict.values():
print(val)
JavaScript
// объект (object)
const obj = { 1: 'a', 2: 'b', 3: 'c' }
// ключи и значения
for (const key in obj) {
console.log(key, obj[key])
}
/*
1 a
2 b
3 c
*/
// еще ключи и значение
Object.entries(obj).forEach(([key, val]) => {
console.log(key, val)
})
// или
for (const [key, val] of Object.entries(obj)) {
console.log(key, val)
}
// ключи
Object.keys(obj).forEach((key) => {
console.log(key)
})
// значения
for (const val of Object.values(obj)) {
console.log(val)
}
36. Отсортировать словарь (объект) по ключам и значениям
Python
dict = { 1: 'b', 3: 'c', 2: 'a'}
# сортировка по значениям
sorted_dict_1 = {
key: val \
for key, val \
# key - критерий сортировки (в данном случае - значение)
in sorted(dict.items(), key = lambda i: i[1])
}
print(sorted_dict_1) # { 2: 'a', 1: 'b', 3: 'c' }
# сортировка по ключам
sorted_dict_2 = { key: val for key, val in sorted(dict.items(), key = lambda i: i[0]) }
print(sorted_dict_2) # { 1: 'b', 2: 'a', 3: 'c' }
JavaScript
// объект для примера пришлось изменить
// поскольку встроенный метод `Object.fromEntries()`
// выполняет автоматическую сортировку по ключам
// при создании объекта из вложенного массива
const obj = { a: '2', c: '1', b: '3' }
// логику сортировки лучше вынести в отдельную функцию
// по умолчанию функция выполняет сортировку по ключам
// благодаря параметру `i` со значением `1` по умолчанию
const sortObj = (obj, i = 0) =>
Object.fromEntries(
// `sort()` принимает функцию для сортировки
// `localeCompare()` сравнивает строки с учетом локали
Object.entries(obj).sort((a, b) => a[i].localeCompare(b[i]))
)
// по ключам
const sortedObj1 = sortObj(obj)
console.log(sortedObj1) // { a: '2', b: '3', c: '1' }
// по значениям
const sortedObj2 = sortObj(obj, 1)
console.log(sortedObj2) // { c: '1', a: '2', b: '3' }
37. Определить, является ли список (массив) пустым
Python
my_list = []
# `not`
if not my_list:
print('Empty')
# + `len()`
if not len(my_list):
print('Empty')
# в `JS` так не получится
if my_list == []:
print('Empty')
JavaScript
const myList = []
// ! - [] -> 0 -> false + ! - false -> true
if (!!myList) {
console.log('Empty')
}
// ! - 0 -> false -> true
if (!myList.length) {
console.log('Empty')
}
// самый очевидный и надежный способ
// или `myList.length === 0`
if (myList.length < 1) {
console.log('Empty')
}
38. Объединить два списка (массива) в один
Python
list_1 = ['a', 'b']
list_2 = list(range(3, 5))
list_2.append('a')
# в `Python` списки можно конкатенировать путем сложения
joined_1 = list_1 + list_2
print(joined_1) # ['a', 'b', 3, 4, 'a']
# распаковка
joined_2 = [*list_1, *list_2]
print(joined_2)
# исключение дубликатов
joined_uniq = list(set(joined_1))
print(joined_uniq) # [3, 'b', 'a', 4]
# модификация списка посредством его расширения
list_2.extend(list_1)
print(list_2) # [3, 4, 'a', 'a', 'b']
JavaScript
const list1 = ['a', 'b']
// еще один встроенный метод для создания массивов
const list2 = Array.of(3, 4)
list2.push('a')
// распаковка
const joined1 = [...list1, ...list2]
console.log(joined1) // ['a', 'b', 3, 4, 'a']
// объединение
const joined2 = list2.concat(list1)
console.log(joined2) // [3, 4, 'a', 'a', 'b']
// исключение дубликатов
// набор (set) сразу преобразуется в обычный массив
const joinedUniq = [...new Set(joined1)]
console.log(joinedUniq) // ['a', 'b', 3, 4]
// модификация массива путем его расширения
list2.splice(-1, 0, ...list1)
console.log(list2) // [3, 4, 'a', 'b', 'a']
39. Извлечь подстроку из строки
Python
my_str = 'I like Python'
# по аналогии со списком
substr = my_str[2:6]
print(substr) # like
JavaScript
const myStr = 'I like JavaScript'
// по аналогии с массивом
const subStr1 = myStr.slice(2, 6)
console.log(subStr1) // like
// специальные встроенные методы
// deprecated
const subStr2 = myStr.substr(2, 5)
console.log(subStr2) // like
const subStr3 = myStr.substring(2, 6)
console.log(subStr3) // like
// разница между методами `substr()` и `substring()`
// состоит в том, включается ли последний элемент в подстроку
40. Функция для получения случайного элемента массива
Python
import random
# import secrets
def get_random_item(list):
if not list:
return 'Empty'
else:
return random.choice(list) # secrets.choice(list)
print(get_random_item(['a', 3, 'c', 1, 'b'])) # 3
JavaScript
// функция для получения случайного целого числа
const getRandomInt = (min, max) => ~~(min + Math.random() * (max - min + 1))
// функция для получения случайного элемента
const getRandomItem = (arr) => arr[getRandomInt(0, arr.length - 1)]
console.log(getRandomItem(['a', 3, 'c', 1, 'b'])) // 'b'
41. Определить количество вхождений элемента в массиве
Python
my_list = ['a', 1, 1, 'a', 2, 'b', 'a']
# `count()`
a_count = my_list.count('a')
print(a_count) # 3
# это также работает для строк
my_str = 'Hello world'
l_count = my_str.count('l')
print(l_count) # 3
JavaScript
const myList = ['a', 1, 1, 'a', 2, 'b', 'a']
const myStr = 'Hello world'
// фильтрация и длина массива
const a_count = myList.filter((i) => i === 'a').length
console.log(a_count) // 3
// преобразуем строку в массив
const l_count = [...myStr].filter((i) => i === 'l').length
console.log(l_count) // 3
42. Объединить два списка (массива) в словарь (объект)
Python
indexes = [0, 1, 2]
languages = ['JavaScript', 'Python', 'PHP']
# `zip()` & `dict()`
my_dict_1 = dict(zip(indexes, languages))
print(my_dict_1) # { 0: 'JavaScript', 1: 'Python', 2: 'PHP' }
# `zip()` и представление списков
my_dict_2 = { k: v for k, v in zip(indexes, languages) }
print(my_dict_2)
JavaScript
const indexes = [0, 1, 2]
const languages = ['JavaScript', 'Python', 'PHP']
// цикл
const obj1 = {}
// нам нужен не только элемент, но и его индекс
// потому что элементы первого массива не всегда будут совпадать с индексами
for (const i in indexes) {
obj1[indexes[i]] = languages[i]
}
console.log(obj1) // { 0: 'JavaScript', 1: 'Python', 2: 'PHP' }
// `reduce()`
const obj2 = indexes.reduce((a, c, i) => {
// `c` - текущий элемент
// `i` - его индекс
a[c] = languages[i]
return a
}, {})
console.log(obj2)
43. Удалить лишние пробелы из строки с помощью регулярного выражения
Python
import re
str_with_spaces = 'some string with many spaces '
# заменяем 2 и более пробела на один
# `sub(regexp, replacement, string)`
str_without_spaces = re.sub(r'\s\s+', ' ', str_with_spaces)
print(str_without_spaces) # some string with many spaces
JavaScript
const strWithSpaces = 'some string with many spaces '
// заменяем 2 и более пробела на один
// `replace(substring | regexp, replacement)`
const strWithoutSpaces = strWithSpaces.replace(/\s\s+/g, ' ')
console.log(strWithoutSpaces) // some string with many spaces
44. Создать перечисления (enum)
Python
from enum import Enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 1
print(Color.RED) # Color.RED
print(Color.GREEN.name) # GREEN
print(Color.BLUE.value) # 3
В JS
не существует такого типа данных, как перечисление, но его можно сымитировать, "заморозив" объект:
JavaScript
const Color = Object.freeze({
RED: 1,
GREEN: 2,
BLUE: 3
})
// value
console.log(Color.RED) // 1
45. Функция для определения анаграмм
Два слова являются анаграммами, если состоят из одинаковых букв. Например, анаграммами являются слова "binary" и "brainy", или "раздвоение" и "дозревание".
Python
def is_anagrams(x, y):
# приводим слова к нижнему регистру
x = x.lower()
y = y.lower()
if (len(x) == len(y)):
# и сортируем их
sorted_1 = sorted(x)
sorted_2 = sorted(y)
if (sorted_1 == sorted_2):
return True
else:
return False
else:
return False
word_1 = 'Binary'
word_2 = 'brainy'
print(is_anagrams(word_1, word_2)) # True
JavaScript
function isAnagrams(x, y) {
x = x.toLowerCase()
y = y.toLowerCase()
if (x.length === y.length) {
sorted_x = x.split('').sort().join('')
sorted_y = y.split('').sort().join('')
if (sorted_x === sorted_y) {
return true
}
return false
}
return false
}
const word1 = 'Раздвоение'
const word2 = 'дозревание'
console.log(isAnagrams(word1, word2)) // true
Обратите внимание: при сравнении строк, состоящих из нескольких слов, необходимо также удалять из них все пробелы.
46. "Капитализировать" строку
Классика.
Python
my_str = 'hello'
# `upper()` + slice
cap_str_1 = my_str[0].upper() + my_str[1:]
print(cap_str_1) # Hello
# `capitilize()`
cap_str_2 = my_str.capitalize()
В JS
отсутствует встроенный метод для капитализации строки.
JavaScript
const str = 'hello'
const capStr1 = str[0].toUpperCase() + str.slice(1)
console.log(capStr1) // Hello
// показать всем, что ты крут ;)
// деструктуризация и шаблонные литералы
const capitilize = ([first, ...rest]) =>
`${first.toUpperCase()}${rest.join('')}`
const capStr2 = capitilize(str)
console.log(capStr2)
47. Функция для определения всех вариантов строки
Python
# рекурсивно
def get_permutations(s, p = [], i = 0):
if i == len(s):
p.append(''.join(s))
for j in range(i, len(s)):
words = [c for c in s]
words[i], words[j] = words[j], words[i]
get_permutations(words, p, i + 1)
return p
print(get_permutations('qux'))
# ['qux', 'qxu', 'uqx', 'uxq', 'xuq', 'xqu']
# `itertools`
from itertools import permutations
per = [''.join(p) for p in permutations('baz')]
print(per) # ['baz', 'bza', 'abz', 'azb', 'zba', 'zab']
JavaScript
function getPermutations(str) {
if (str.length < 2) {
return str.length === 2 ? [str, str[1] + str[0]] : [str]
}
return str
.split('')
.reduce(
(a, c, i) =>
a.concat(
getPermutations(str.slice(0, i) + str.slice(i + 1)).map((v) => c + v)
),
[]
)
}
console.log(getPermutations('qux'))
// ['qux', 'qxu', 'uqx', 'uxq', 'xqu', 'xuq']
48. Создание счетчика (таймера)
Python
import time
def timer(time_in_sec):
while time_in_sec:
m, s = divmod(time_in_sec, 60)
formated = f'{m:02d}:{s:02d}'
print(formated, end = '\r')
time.sleep(1)
time_in_sec -= 1
timer(5)
JavaScript
function timer(timeInSec) {
const timerId = setInterval(() => {
let m = ~~(timeInSec / 60)
let s = timeInSec - m * 60
if (m < 10) m = '0' + m
if (s < 10) s = '0' + s
console.log(`${m}:${s}`)
timeInSec -= 1
if (timeInSec < 0) {
clearInterval(timerId)
}
}, 1000)
}
timer(5)
49. Создание вложенной директории
Пусть 2 последних задачки будут посвящены бэку.
Python
import os
# абсолютный путь к текущей директории
__dirname__ = os.path.abspath(os.getcwd())
# небезопасно: при наличии создаваемой директории будет выброшено исключение
try:
os.makedirs(f'{__dirname__}/parent/child/nested')
except FileExistsError:
print('Exists')
import distutils.dir_util
# безопасно
distutils.dir_util.mkpath(f'{__dirname__}/some/dir')
JavaScript
import { dirname } from 'path'
import { fileURLToPath } from 'url'
import { promises as fs } from 'fs'
// абсолютный путь к текущей директории
const __dirname = dirname(fileURLToPath(import.meta.url))
// безопасно
// для сравнения обработки исключений
try {
await fs.mkdir(`${__dirname}/parent/child/nested`, { recursive: true })
} catch (e) {
console.error(e.message || e)
}
Обратите внимание: приведенный код должен запускаться с помощью команды node filename
. При этом файл должен быть модулем, т.е. иметь расширение .mjs
или же в ближайшем package.json
должно содержаться поле type
со значением module
.
50. Получение названий файлов с расширением ".txt"
Предположим, что у нас имеется директория files
с тремя файлами в формате TXT
. Как нам получить названия этих файлов?
Python
import glob, os
__dirname__ = os.path.abspath(os.getcwd()) + '/files'
def get_filenames(ext):
filenames = []
# читаем содержимое директории `files`
os.chdir(__dirname__)
# если файл имеет указанное расширение
for filename in glob.glob(f'*.{ext}'):
# добавляем его в список
filenames.append(filename)
# возвращаем список
return filenames
print(get_filenames('txt'))
# ['baz.txt', 'foo.txt', 'bar.txt']
JavaScript
import { dirname } from 'path'
import { fileURLToPath } from 'url'
import { promises as fs } from 'fs'
const __dirname = dirname(fileURLToPath(import.meta.url))
async function getFilenames(ext) {
const result = []
// читаем содержимое директории `files`
const filenames = await fs.readdir(`${__dirname}/files`)
for (const filename of filenames) {
// если файл имеет указанное расширение
if (filename.includes(`.${ext}`)) {
// добавляем его в массив
result.push(filename)
}
}
return result
}
// функция возвращает промис
getFilenames('txt').then(console.log)
// [ 'bar.txt', 'baz.txt', 'foo.txt' ]
Фух… это было утомительно, но, вместе с тем, невероятно увлекательно, не правда ли?
Как видите, синтаксические конструкции и основной функционал JavaScript
и Python
являются очень похожими, а во многом даже идентичными (без учета некоторых незначительных отличий), что при необходимости позволяет с относительной легкостью перейти с одного языка на другой.
Вопрос в том, имеется ли необходимость в такой "миграции"?
Обратите внимание: дальше я выскажу собственное мнение с позиции веб-разработчика.
Существенное преимущество JavaScript
заключается в том, что он не нуждается в интерпретаторе, т.е. код на JS
выполняется браузером напрямую. Это очень сильно облегчает разработку веб-приложений.
Если мы говорим о REST API
, то реализовать его на Express
, например, намного проще, чем на Django
или FastAPI
, хотя последний синтаксически схож с сочетанием Express
и TypeORM
или Prisma
(во многом благодаря широкому использованию декораторов).
С другой стороны, если мы говорим о реализации, скажем так, продвинутого сервера, то благодаря огромному количеству, в том числе, встроенных модулей, Python
имеет некоторые преимущества перед Node.js
.
Есть мнение, что у Python
имеются некоторые проблемы с асинхронностью — у меня не было возможности в этом убедиться.
В свою очередь, в Node.js
в последнее время царит некоторая неразбериха за счет одновременного существования двух разных подходов к разработке: одного, основанного на колбеках, который считается устаревшим, и другого, основанного на промисах и async/await
, который требует дополнительных усилий по настройке окружения и не в полной мере заменяет первый подход.
Благодарю за внимание и хорошего дня!
Комментарии (52)
ykosyakov
21.09.2021 11:20+4Что имеется в виду под дополнительной настройкой окружения для работы с promise/async-await?
menstenebris
21.09.2021 11:24+24В статье произошёл рассинхрон. Делаем 50 приседаний на сложение/вычитание, а в выводе объявляем что node лучше django, а асинхронность в питоне плохая. Надо либо вывод по математическим приседаниям делать, либо исследовать фреймворки и асинхронность.
abutorin
21.09.2021 11:26-1Существенное преимущество
JavaScript
заключается в том, что он не нуждается в интерпретаторе, т.е. код наJS
выполняется браузером напрямую. Это очень сильно облегчает разработку веб-приложений.Что значит выполняется напрямую? В браузере уже нет встроенного интерпритатора? Или вы хотели сказать что в браузере нельзя выполнять код написанный на python напрямую? А что такое разработка веб-приложений? Это только клиентская часть, или и северная тоже? Запустить код на сервере что на python, что на javascript одинаково легко.
Nehc
21.09.2021 13:08>>> В браузере уже нет встроенного интерпритатора?
Есть. Для JS. Для Питона нет. Я думаю речь об этом.
Код на JS может отработать на странице, которую вы написали в блокноте, сохранили локально и открыли в любимом браузере.<script type="application/javascript"> alert('Hello, World!'); </script>
Я не специалист (ни в js, ни в py), но с питоном такая тема, как мне кажется, невозможна… Или я чего-то не знаю?abutorin
21.09.2021 13:29любимом браузере
Бразурер это тоже программа, она должна быть установлена. На многих компьютерах интерпритатор питона тоже установлен, и его запустить можно точно также, просто написал код в простом блокноте.
suns
21.09.2021 16:18+2Ага, много разных версий питона, причем далеко не везде, из-за чего при распространении ПО на питоне всегда надо встраивать интерпретатор в бандл с питоном
abutorin
21.09.2021 16:26-1разных версий питона
По моему опыту, для большей части кода важно 2-й это питон или 3-й. Внутри мажорной версии проблем с обратной совместимостью я не встречал. Использовать только определённую версию может потребоваться только при подключении внешних библиотек написанных например на C. Ну так с чистым javascript тоже самое, не говоря уже про разные движки для него. С движками сейчас только стало полегче после появления явного лидера.
unsignedchar
21.09.2021 20:00+1Внутри мажорной версии проблем с обратной совместимостью я не встречал.
Напримерexcept (AttributeError, ValueError):
Поддержку этой конструкции выпилили, если не ошибаюсь, в python 3.6, и некоторые скрипты при обновлении внезапно перестали работать. Особенно забавно, когда это давно не обновлявшаяся библиотека, которую притащил pip.abutorin
21.09.2021 20:06Поддержку этой конструкции выпилили
Странно. В документации описан именно такой пример:
https://docs.python.org/3/tutorial/errors.html#handling-exceptions
unsignedchar
21.09.2021 21:33Возможно, это что-то другое было. Deprecated в 3.6 и окончательно выпилено в 3.8. При переезде с 18.04 на 20.04 оно себя именно так проявило — как syntax error. Нужно будет перепроверить ;) Завтра поищу тот кусок кода.
bankir1980
21.09.2021 15:34На самом деле в тег script можно интегрировать любой скриптовый язык. Только вот работать будет не везде. Помнится 15 лет назад баловался запуская код в IE в теле script, написанный на RSL. Это язык, используемый в банковской системе RS-Bank. Для этого нужно было всего лишь установить какую-то dll в Винде от разработчика RS-Bank. К сожалению материалов по этому в интернете не нашёл.
Кстати. Тогда и VBScript в IE работал и именно его я начинал использовать вместо JS.
NN1
21.09.2021 15:42Нативно есть только JavaScript или WASM.
Для демонстрации Python можно взять Brython: https://brython.info/
gleb_l
21.09.2021 11:53+2Для Питона хочется сделать препроцессор, чтобы можно было писать в C-like нотации, которая одновременно и лаконичная, и четко визуально определяемая - но тогда Питон превратится в JavaScript ;)
С непривички глаз царапается двоеточиями там, где должно быть начало блока и этой ужасной концепцией отступов, как окончаний. Говорят, что очень сложно одновременно грамотно писать на русском и белорусском - так как правила правописания там полярны. Видимо после плотного питонизма автоматизм ставить закрывающие фигурные скобки тоже будет утрачен :)
victoriously
21.09.2021 19:18-2этой ужасной концепцией отступов, как окончаний.
А чем она ужасна? Тем, что отучает писать код без форматирования и однострочники? Это же прекрасно.
gleb_l
21.09.2021 19:23+3Тем, что не оставляет писателю выбора. Поэты пишут лесенкой, но конец предложения - всегда точка. Также и в языках программирования. Иногда нагляднее записать в одну строку, иногда разнести отступами. Если есть явный конец блока - у меня есть эта свобода. Если его нет - то этой свободы нет.
kai3341
21.09.2021 23:37-2О, нашёлся великий поэт. Codestyle? Не, не слышал. Production требует линтов, форматтеров и тайп чекеров имеено из-за обилия великих поэтов.
gleb_l
22.09.2021 13:00+1Ассоциирование автора аллегории с субъектом, в ней описанным - довольно странная затея, более характерная для описанной Жванецким категории "Зачем спорить с хромым об искусстве, когда можно сразу ему сказать, что он хромой"
По поводу же синтаксиса - код смотрят не только в IDE в окружении подпорок-линтеров. Могут посмотреть и в нотепаде, и даже (архаика!) на бумаге. И без подпорок ориентироваться на пробелы очень сложно. Поэтому отсутствие видимого глазом закрывающего блок символа - в общем случае рискованное предприятие.
С другой стороны, мотивы разработчиков Питона понятны - нужно отрываться от парадигм (как когда-то ушли от номеров строк и фиксированных позиций в Фортране), и смотреть в будущее без бумаги и нотепадов. Тем более, что входящие в IT люди не имеют инстинктивной практики следить за блоками, но легко перенимают эстетику отступов (красивый самолет и летает хорошо)
kai3341
25.09.2021 04:08Ассоциирование автора аллегории с субъектом, в ней описанным - довольно странная затея, более характерная для описанной Жванецким категории "Зачем спорить с хромым об искусстве, когда можно сразу ему сказать, что он хромой"
Занимайтесь "искусством" сколько влезет. Главное, в коммерческую разработку не лезте. Там и без вашего "искусства" проблем выше крыши.
Хотя следует признать, что 95% проблем носят рахитектурный характер. Банальное соблюдение хотя бы SRP -- это заоблачное ожидание от людей "искусства".
По поводу же синтаксиса - код смотрят не только в IDE в окружении подпорок-линтеров. Могут посмотреть и в нотепаде, и даже (архаика!) на бумаге. И без подпорок ориентироваться на пробелы очень сложно. Поэтому отсутствие видимого глазом закрывающего блок символа - в общем случае рискованное предприятие.
Не распечатывайте на бумаге
yaml
, пожалуйста.Что до обмазывания линтерами и форматтерами -- к сожалению, это необходимость. Бороться с линтером и форматтером, всобачивая изредка в код
# noqa
и# fmt: on/off
или// prettier-ignore
сильно проще, чем спорить с опытными и адекватными людьми, которым стрельнуло утворить дичь.Что до "нотпада" -- иногда так случается, что хитрый баг воспроизводится только на проде. Я понимаю, что вы привыкли к "нотпадам" на серверах -- уж простите, но мы выбираем между
nano
иvim
. Вот отсюда и далее у меня возникает стойкое ощущение, что лыжи не едут вовсе не у меня.Да, на бумаге код ни разу не печатал, каюсь. Кстати, а вы?
С другой стороны, мотивы разработчиков Питона понятны - нужно отрываться от парадигм (как когда-то ушли от номеров строк и фиксированных позиций в Фортране), и смотреть в будущее без бумаги и нотепадов. Тем более, что входящие в IT люди не имеют инстинктивной практики следить за блоками, но легко перенимают эстетику отступов (красивый самолет и летает хорошо)
Правильно ли я понимаю, что минифицированный JS со скобочками и
;
вам читать легче, чем код на python? Что-то мне подсказывает, что вы не честны даже с самим собой. Любой психически здоровый разработчик выделит вложенный блок отступом. Вложенный блок (подвыражение) может выделяться скобками как обычными -- это справедливо для большинства языков. Вложенный блок может выделяться фигурными скобками, а также выражениямиbegin/end
,if/fi
+for/done
+while/loop
и прочими.Теперь вопрос: если вложенный блок уже выделен отступом -- нужен ещё один синтаксис выделения блока?
ehots
21.09.2021 12:13+3Читаешь статью от школьника который написал довольно хороший клон хабра, а потом видишь это и от списка задач глаза широко открываются. А Вы в каком классе учитесь?
Ну и в целом полнейшая отсебятина притянутая за уши...
Goodwinnew
21.09.2021 12:13-2Питон на сервере. Для вебразработки.
Да, там он работает. Как модуль Апач.
А если мы хотим без Апач, что бы быстро и много пользователей одновременно (через связку NginX->PHP FPM), то Питон тут уже не гуд.
Посдкажите, плиз. Я правильно понимаю?
menstenebris
21.09.2021 12:16+2Нет. Для питона есть свои wsgi и asgi веб серверы. например uwsgi, gunicorn, nginx-unit.
stepalxser
21.09.2021 12:26+1Маленькие замечания по питону:
1)lambda — синтаксис для анонимных функций и используются однократно, например в сортировках. Если нужно переиспользовать, то стоит обьявлять синтаксис с def.
2)Внутри f-строк не стоит производить вычисления и/или вызовы функций, желательно передавать уже готовые значения.
3)В питоне есть красивый синтаксический сахар в виде генераторов выражений, который позволяет не использовать нагромождение map|filter|lambdaTimergaleev
21.09.2021 19:00+1Внутри f-строк не стоит производить вычисления и/или вызовы функций, желательно передавать уже готовые значения.
Можете пояснить почему: какой-то этический момент python, или это связано с возможным ухудшением производительности?
stepalxser
21.09.2021 22:48В целом, это достаточно холиварный момент. Общего соглашения в виде pep'a нет, кто-то использует, кто-то нет.
Но это сильно портит читаемость кода и потихоньку приходят к решению, что это — антипаттерн.
kai3341
21.09.2021 22:14Два чаю вам за этот комментарий. Внесу некоторые пояснения
1) Дело в том, что гениальный JS фундаментально разделяет обычные функции и стрелочные функции (то, что в других языках называют лямбдами). И ввиду этих фундаментальных различий это на самом деле 2 разных инструмента
2) Удваиваю и отвечу @Timergaleev -- на таких f-строках слишком легко допустить исполнения достаточно тяжёлого кода. Поясню -- основная проблема в исполнении потенциально ненужного кода (привет, логгирование), который при этом может оказаться ещё и тяжёлым
3) map/filter лучше всего комбинировать с готовыми функциями. То есть если есть кирпичики -- map/filter. Нет кирпичиков -- синтаксис генераторов. Сложная логика в генераторе -- таки выносим её в кирпичики и или возвращаемся к map/filter, или всё делаем на yield (который в JS тоже кстати есть)
Alexandroppolus
22.09.2021 00:35JS фундаментально разделяет обычные функции и стрелочные функции (то, что в других языках называют лямбдами)
"фундаментальное" различие там только во внешних this/arguments для стрелочных функций. На представленных примерах это никак не проявится. Так что менять одно на другое можно без проблем, просто стрелки короче.
yakimka8
21.09.2021 12:36-5По первому же примеру видто что вы не питонист
print('Hello world!')
Иначе вы бы знали, что у питона батарейки в комплекте:
import __hello__
sshikov
21.09.2021 13:08+2>По первому же примеру видто что вы не питонист
Это написано у автора прямо в первом же предложении.
Nehc
21.09.2021 13:12+5для сравнения синтаксиса двух языков использование import __hello__ — это конечно прям то, что надо, ага… ;)
IonianWind
21.09.2021 12:57В свою очередь, в
Node.js
в последнее время царит некоторая неразбериха за счет одновременного существования двух разных подходов к разработке: одного, основанного на колбеках, который считается устаревшим, и другого, основанного на промисах иasync/await
, который требует дополнительных усилий по настройке окружения и не в полной мере заменяет первый подход.Это как так? Под настройкой окружения, как я понимаю, имелся в виду какой-нибудь
babel
.async/await
из коробки вNode.js
уже c 7-й версии есть,Promise
- и того раньше.Так что более 4-х лет никакое окружение настравать не надо.
niko1aev
21.09.2021 13:30+6Мне кажется сравнивать языки путем написания одного метода/функции - не корректно.
Это сродни тому, что сказать, что в Numbers и Excel одинаково работает SUM, поэтому они очень похожие и можно легко прыгать с одного на другой. Сродни тому, что сказать, в Google Sheets и в SAP можно создать таблицу с заголовками, поэтому можно легко не платить за SAP и пересесть на Google Sheets
Если сравнивать языки, то надо не забыть про
- наследование и прототипы
- встроенные в язык библиотеки/модули
- обработку ошибок
- весь синтаксический сахар
- обновление языка, совместимость, процент тех, кто сидит на последней версии
- и многое-многое другое
Конкретно про Web-разработку - еще больше всего.
А то так можно порешать задачки на Go и TypeScript и обнаружить, что они очень похожи)
Но при этом они настолько разные, что их даже и сравнивать-то глупо. Как карьерный самосвал и железнодорожный локомотив
Alexandroppolus
21.09.2021 13:36+1невероятно увлекательно, не правда ли?
Нет. Интересной здесь была только задачка 4 про площадь, и только для Герона Александрийского..
mapron
21.09.2021 20:23А мне понравилось. Я вот не знал решения большинства задач, в том числе вычисления площади треугольника (с математикой сталкиваться не приходится).
forthuse
21.09.2021 14:15Решил 50 задач и ответил на вопрос — Python или JavaScript?
Не смотрели для сравнения существующих решений этих и других задач на http://rosettacode.org?
P.S. Интересно, что на rosettacode.org JavaScript 744 решённых задач ,
а на Python — 1,269 и в 18-ти категориях
eandr_67
21.09.2021 15:34+2Какой-то детский сад от студента, только начинающего осваивать программирование.
Предложенная функция определения простого числа имеет сложность O(n), хотя достаточно O(√n): если n — составное число, то один из множителей заведомо не превышает √n.
Функция определения високосного года переусложнена. Автор не знает способы упрощения логических выражений?
В JS только and и not поменять на && и ||.return ['not leap', 'leap'][year % 4 == 0 and (year % 100 or year % 400 == 0)]
Определение чётности в Python:
В JS остаток отрицательного делимого — отрицательное число, потому проще использовать битовые операции:return ['even', 'odd'][n % 2]
return ['even', 'odd'][n & 1];
Предложенные автором функции вычисления НОД и НОК — откровенная безграмотность:def gcd(a, b): while b: a, b = b, a % b return a def lcm(a, b): return a * b // gcd(a, b)
И т.д. по списку…
Druj
21.09.2021 15:43+1Что я только что проскроллил? Смысл всей работы это сравнение синтаксиса стандартных библиотек двух никак не пересекающихся языков. Надеюсь автор хоть печатать быстрее научился, иначе совсем всё зря.
valkyr
21.09.2021 16:20-1const myList = []
// ! - [] -> 0 -> false + ! - false -> true
if (!!myList) { console.log('Empty') }
Добро пожаловать в мир пустых массивов, всех, абсолютно!
vlasenkofedor
21.09.2021 16:20+2Да, Хабр стал более доступен для "школьников"
Личное мнение, такие материалы нужно скрывать.
Примеры сделаны без понимания математики, алгоритмов и булевых операций.
Aleksandr-JS-Developer
21.09.2021 19:01индикатором отсутствия значения в
Python
являетсяNone
, а вJS
у нас целых 3 таких индикатора —undefined
,null
иNaN
В JS индикатором отсутствия значения является только null.
undefined
значит, что переменная существует, но значения не имеет.
NaN вообще значит, что в переменной не число. Но никак не "пусто".abutorin
21.09.2021 20:11undefined
значит, что переменная существует, но значения не имеет.А как же обращение к свойству объекта которого у объекта нет?
savostin
21.09.2021 21:53;[x, y] = [y, x]
Объясните кто-нибудь пожалуйста.
eandr_67
21.09.2021 22:13+1Точка с запятой перед '[' нужна только потому, что автор принципиально не ставит точек с запятой после операторов. Такое пренебрежение ';' допустимо в JS, но является дополнительным источником ошибок. Потому — на всякий случай — автор впихнул ';' перед присваиванием: очередное героическое преодоление собственноручно созданных трудностей.
Что касается [x, y] слева от присваивания, то это называется «деструктуризация массива» и описывается в любом современном учебнике. Например: learn.javascript.ru/destructuring-assignment
Если своими словами, то элементы массива справа от '=' присваиваются переменным, перечисленным в [] слева от '='. Т.е., упрощая, при выполнении [x, y] = [y, x]; сначала создаётся массив tmp = [y, x], а потом производится 2 присваивания: x = tmp[0] и y = tmp[1].savostin
21.09.2021 22:23Про деструктуризацию был в курсе.
А вот ; поставило в ступор.
Так и не понял зачем оно там. И так все работает. Автор ещё на этом заостряет внимание будто это важно...
eandr_67
22.09.2021 16:53+1У автора в статье много странного кода. Единственное вменяемое объяснение этой абсолютно ненужной ';' я вижу в том, что автор опасается, что данное выражение может быть склеено интерпретатором JS с выражением в предыдущей строке кода (в конце которого автор принципиально ';' не поставил).
Хотя, скорее всего, это простое непонимание автором того, что и зачем он делает. Такое же непонимание, как вычисление НОД и НОК последовательным перебором чисел в цикле или вычисление циклом суммы арифметической прогрессии.
dimoff66
23.09.2021 09:30Это действительно важно, пример автора работает и без нее, но если написать
```
let x = 1
let y = 2
[x, y] = [y, x]
```
Подобный код не скомпилируется
Поэтому точка с запятой перед выражением, начинающимся с квадратных скобок, дает гарантию корректной компиляции подобной строчки вне зависимости от того, какой код находится выше.
fireSparrow
В Яндексе тоже есть Go, и его там тоже любят. Просто в инфраструктурных командах и в критичных по производительности местах удобнее Go, а для сложной бизнес-логики и перекладывания джсонов лучше подходит питон.
Tsentr
JS JSONы хуже питона перекладывает?
fireSparrow
Я JS не очень глубоко знаю, и его эффективность в перекладывании джсонов не берусь оценивать. Но по совокупности плюсов и минусов в целом по индустрии для бэкенда питон считается более подхлдящим, чем JS.