Страницы

Поиск по вопросам

пятница, 27 декабря 2019 г.

Почему нельзя запустить android приложение на Linux?

#java #android #linux


Здравствуйте! Почти все приложения для Android написаны на Java. И тем не менее их
нельзя запустить на компьютере. Почему? А если перекомпилировать?
В чем разница между Java на Android и Linux? Можно их запустить на компьютере?
    


Ответы

Ответ 1



Во первых Андроид это операционная система и работает на виртуальной машине по жавой. Хоть и сделана на база линукса они разные, разные библеотеки, дрова и тд. Тем более приложение компилируется на архитектуру процессоров ARM. Но запустить на компе возможно с помощью эмулятора, па пример Genymotion.

Ответ 2



Десктопная Java работает на Sun'овской виртуальной машине JVM Android'ная Java работает на виртуальной машине Dalvik, которая по байткоду несовместима с JVM Начиная с Kitkat Android начал переход на новую виртуальную машину ART (Android Runtime) Существуют перекомпиляторы с байткода JVM на Dalvik и обратно. Стандартно это делается с помощью утилиты dx встроенной в Android SDK. Но проблема в том, что это не поможет, поскольку Java байткод будет вызывать встроенные нативные функции телефона отсутствующие в десктопе. Единственный выход - это запускать APK файлы в окружении эмулятора: либо на GenyMotion, который работает поверх Ораклевской виртуалки, либо стандартного AVD устройства идущего в комплекте с Android SDK. Update Сообщается, что выпущен плагин для браузера Chrome, который позволяет запускать Андроид приложение в окружении браузера: втыкаем и читаем

Ответ 3



ARC Welder пытается решить проблему запуска Android-приложений на десктопе. Пока, похоже, не слишком удачно.

Переменные-ссылки в Python

#python #указатели #ссылки


Я так понял, что все переменные в Python - это ссылки, которые ссылаются на один
объект, а не на участок памяти как в С/C++. 

А есть ли возможность создания ссылки на один участок памяти, чтобы изменялось значение
при работе с любой из ссылок?

Например (условно),

a = 10
b = &a
print(a, b)  # 10 10
b = 20
print(a, b)  # 20 20
a = 15
print(a, b)  # 15 15


Мне это нужно, чтобы сокращать запись для доступа ко внутренним значениям вложенных
словарей:

username   = "test"
userdata   = [10, 2, 30, 15]
user       = {username:userdata}

serveraddr = "127.0.0.1"
server     = {serveraddr:user}

# хочется создать имена-сокращения для этих элементов    
joincount  = server[serveraddr][username][0]
leftcount  = server[serveraddr][username][1]
gamescount = server[serveraddr][username][2]
wincount   = server[serveraddr][username][3]

# пробуем изменить их значения
joincount  = 20
leftcount  = 9
gamescount = 10
wincount   = 3

# проверяем, что значения в словаре остались прежними
print(server[serveraddr][username][0], server[serveraddr][username][1],
      server[serveraddr][username][2], server[serveraddr][username][3])
# (10, 2, 30, 15)

# хотя значения переменных изменились
print joincount, leftcount, gamescount, wincount
# (20, 9, 10, 3)


В коде очень часто используются конструкции вида server[serveraddr][username][n],
большая их часть приходится на места где все индексы вычислены. Поэтому хотелось бы
вместо server[serveraddr][username][0] использовать joincount - это улучшило бы читаемость
кода.

Возможно ли это реализовать?
    


Ответы

Ответ 1



В Python есть изменяемые и неизменяемые типы. Изменяемые отличаются тем, что их содержимое можно сменить, не изменив ссылку на них. Неизменяемые объекты приходится пересоздавать, чтобы отразить изменения состояния. При этом все старые ссылки не видят это обновление, потому что указывают на старый объект. Поясню на практике. Списки, словари, множества - это изменяемые объекты: l1 = [1, 2, 3] l2 = l1 print(l1, l2, id(l1), id(l2)) # [1, 2, 3] [1, 2, 3] 139917408901064 139917408901064 l1[1] = 10 print(l1, l2, id(l1), id(l2)) # [1, 10, 3] [1, 10, 3] 139917408901064 139917408901064 Числа, строки, кортежи - это неизменяемые объекты: v1 = 1024 v2 = v1 print(v1, v2, id(v1), id(v2)) # 1024 1024 ...7040 ...7040 v1 = 2048 print(v1, v2, id(v1), id(v2)) # 2048 1024 ...5312 ...7040 t1 = (1, 2, 3) t2 = t1 print(t1, t2, id(t1), id(t2)) # (1, 2, 3) (1, 2, 3) ...6232 ...6232 # t1[1] = 10 # не сработает, так как кортежи неизменяемые t1 = (1, 10, 3) print(t1, t2, id(t1), id(t2)) # (1, 10, 3) (1, 2, 3) ...7240 ...6232 В своём коде вы используете изменяемые структуры данных, такие как словари и списки (user, userdata, server) и неизменяемые строки и числа. Таким образом, ничего не изменяя в структуре хранения информации, максимально можно сократить только доступ до списка чисел my_userdata = server[serveraddr][username] # изменение my_userdata влечёт изменение server[serveraddr][username], # так как это один и тот же объект Так как числа неизменяемые, то сохранение их в переменную и дальнейшее изменение этой переменной никак не сказываются на исходном числе (т.е. переменная joincount никогда не изменится при изменении server[serveraddr][username][0], и наоборот). изменение чисел в этом списке никак не отразится на переменных, хранящих эти значения Но если попробовать немного улучшить код, то стоит создать класс UserData, который будет хранить в себе нужные значения и позволять их изменять. Минимальный пример будет следующий: class UserData: def __init__(self, joincount, leftcount, gamescount, wincount): self.joincount = joincount self.leftcount = leftcount self.gamescount = gamescount self.wincount = wincount username = "test" userdata = UserData(10, 2, 30, 15) user = {username:userdata} После этого, если мы получаем откуда-то нашего пользователя, мы можем изменить нужные значения: user_data = server[serveraddr][username] user_data.joincount = 20 user_data.leftcount = 9 user_data.gamescount = 10 user_data.wincount = 3 print (server[serveraddr][username].joincount, server[serveraddr][username].leftcount, server[serveraddr][username].gamescount, server[serveraddr][username].wincount) print (user_data.joincount, user_data.leftcount, user_data.gamescount, user_data.wincount) Использование подобной структуры увеличит читаемость вашего кода, по сравнению с использованием индексов списка. Если есть доступ на изменение содержимого словаря, я бы рекомендовал вам вместо самописного класса использовать namedtuple из стандартного модуля collections, который позволяет создавать объект, по поведению схожий с кортежем, но предоставляющий доступ к полям, как у класса выше (но только на чтение): UserData = collections.namedtuple('UserData', ['joincount', 'leftcount', 'gamescount', 'wincount']) В этом случае придётся заменять старый объект UserData новым: old_userdata = server[serveraddr][username] new_userdata = UserData(joincount=20, leftcount=9, gamescount=10, wincount=3) server[serveraddr][username] = new_userdata print(new_userdata, old_userdata, server[serveraddr][username]) Получение поля на чтение будет выполняться так же, как и в примере выше: print(old_userdata.joincount, old_userdata.gamescount)

Ответ 2



Вам нужно прочитать и разобраться с mutable и immutable объектами в python. Да вы можете делать ссылку на вложенный список, и заполнять его через нее. Например: lst = [[]] sublst = lst[0] sublst.append(1) print(lst) sublst.append(2) print(lst) print(id(lst[0])) print(id(sublst)) sublst[0] = -1 print(lst) Вывод: [[1]] [[1, 2]] 139794716732424 139794716732424 [[-1, 2]] В данном случае sublst это ссылка на вложенный список в lst, вызов sublst.append равнозначен lst[0].append. Аналогично вы можете работать например со словарем.

Как добавить обработчик нажатия на элемент в RecyclerView?

#java #android #recyclerview


Мне нужен горизонтальный лист вью. Стал рыть в интернете, и нашел совет юзать RecyclerView.
Вроде это новая штука от гугл и тд. Вобщем вставил я его себе в проект. Выводит он
все нормально. Написал адаптер и тд. Но как теперь написать обработчик нажатия на айтем???
нашел реализацию этого всего вот тут RecyclerView onClick

Но в итоге получаю такое:

mRecyclerView.addOnItemTouchListener(
                new RecyclerItemClickListener(this, new RecyclerItemClickListener.OnItemClickListener() {
                    @Override public void onItemClick(View view, int position) {
                        Toast.makeText(DashboardActivity.this, "dfsdg"+ position,
Toast.LENGTH_LONG ).show();
                    }
                })
        );


как мне вместо "dfsdg"+ position вывести элемент моего списка??? гугл в очередной
раз меня огорчил.

ДОПОЛНИЛ

я добавил метод в адаптер:

public User getItem(int position){
    return userList.get(position);
}


теперь я имею возможность из вне вытащить свой айтем:

@Override
public void onItemClick(View view, int position) {
    Toast.makeText(DashboardActivity.this, ((RecyclerAdapter)mAdapter).getItem(position).getUserInfo().getName(),
Toast.LENGTH_LONG ).show();
}


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

Как-то так:

public void onItemClick(AdapterView adapterView, View view, int i, long l) {
    adapterView.getAdapter().getItem(i)......
}


adapterView, а не передавать свой адаптер.
    


Ответы

Ответ 1



Для начала, почему же google не реализовала интерфейс onItemClickListener в своем новом виджете RecyclerView. Объясняется это тем, что данный интерфейс был весьма не совершенен и, в частности, создавал определенные трудности для обработки кликов на вложенных элементах айтема, также были определенные проблемы с получением реальной позиции и некоторые другие. Чтобы избавить себя от подобных проблем google решила доверить реализацию этого сомнительного действия самому программисту ... что же, какие у нас есть варианты. В первую очередь нужно понять, какого экшена мы чаще всего ожидаем от клика по элементу списка? Как правило это переход к другой активити со значением кликнутой позиции (каких то связанных с этой позицией данных адаптера и тп). Реализовать такое простое действие можно просто повешав слушатель прямо в адаптере. Здесь у нас есть доступ к текущей позиции и всем данным адаптера: @Override public void onBindViewHolder( ItemHolder holder, int position) { holder.someView.setOnClickListener (new View.OnClickListener() { @Override public void onClick(View v) { // action on click } }); } Однако IP696 в своем комментарии был прав, вешать сложную логику (если такая вдруг потребовалась для обработки клика по айтему) в адаптер не разумно. Следующий вариант - положить на доводы google и реализовать интерфейс onItemClicklListener() самостоятельно. При такой реализации мы можем передать "на сторону" через интерфейс множество полезных вещей: позицию, данные адаптера по кликнутому айтему, view айтема и тд. , но лишаем себя удобной возможности простым способом обрабатывать клики на дочерних элементах, как это можно было сделать в первом варианте и о чем предупреждал нас google. Кроме того, фактически, как правило, нет никакой прямой необходимости обрабатывать клик по айтему на "внешней" стороне. Пример: public class ListAdapterHolder extends RecyclerView.Adapter { OnItemClickListener mItemClickListener; @Override public ViewHolder onCreateViewHolder(ViewGroup parent , int viewType) { ... return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder , int position) { ... } public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public ViewHolder(View view) { super(view); view.setOnClickListener(this); ... //здесь можно повесить слушатель и на отдельные виджеты в айтеме } @Override public void onClick(View v) { if (mItemClickListener != null) { mItemClickListener.onItemClick(v, getAdapterPosition()); } } } public interface OnItemClickListener { public void onItemClick(View view , int position); } public void SetOnItemClickListener(final OnItemClickListener mItemClickListener) { this.mItemClickListener = mItemClickListener; } } Наиболее логичным решением ситуации я считаю решение обрабатывать клики в классе-холдере адаптера. Здесь у нас есть простой и прямой доступ ко всем элементам айтема, данные самого адаптера (так как класс вложен в адаптер) для простого добавления\изменения\удаления пунктов списка, кроме того через конструктор можно передать дополнительные данные, кроме, собственно View, также логика обработки кликов выведена из адаптера в статический холдер: public static class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener { TextView mText; Button mButton; CardView mCard; public ItemHolder(View v) { super(v); mCard = (CardView) v.findViewById(R.id.item_card); mText = (TextView) v.findViewById(R.id.item_text); mButton = (Button) v.findViewById(R.id.item_button); mCard.setOnClickListener(this); mButton.setOnClickListener(this); } @Override public void onClick(View v) { int position = getAdapterPosition(); if (position != RecyclerView.NO_POSITION) { switch (v.getId()) { case R.id.card: itemClick(position); break; case R.id.button: buttonClick(position); } } } private void itemClick(int position){ //action on item click } private void buttonClick (int position){ //action on button click } } Так же, если клик нужно обработать в активити, то можно просто указать в xml-разметке айтема списка метод обработки клика (android:onClick) и реализовать его в активити. Подробнее

Ответ 2



Ответ @pavlofff верен. Единственный вопрос где обработать нажатие. В своем проекте мы используем для этого шину событий (Otto by Square). Что то вроде: public class Adapter extends RecyclerView.Adapter { @Inject Bus bus; @Override public void onBindViewHolder( ItemHolder holder, final int position) { holder.view.setOnClickListener (new View.OnClickListener() { @Override public void onClick(View v) { bus.post(new ItemClickedEvent(getItem(position))); } }); } } В нужном месте ловим ItemClickedEvent, который содержит в себе модель, ячейка с которой была выбрана. Странно, конечно, что Google не добавила callback как для listview.

Развернуть слово

#строки #char


Надо развернуть слова наоборот, чтобы при этом небуквенные символы оставались на
своих местах.

Например:
a1bcd => d1cba
    


Ответы

Ответ 1



Заводим указатели на начало и конец строки, идем в цикле, первый указатель увеличиваем, второй уменьшаем, цифры проскакиваем. Меняем между собой буквы на которые смотрят указатели. Завершаемся, когда указатели сравнялись. В виде кода как то так (правда вы язык не указали): int j = 0; int k = ch.length-1; while(j

Ответ 2



var s = "a1bcd"; var rev = s.match(/[a-z]/gi).reverse(), i = 0; var res = s.replace(/[a-z]/gi, m => rev[i++]); console.log(res);

Ответ 3



На C#: public string ReverseSkippingNonLetters(String source) { var result = new StringBuilder(); for (int i = 0; i < source.Length; i++) { Char forward = source[i], backward = source[source.Length - i - 1]; if(!Char.IsLetter(forward)) result.Append(forward); if(Char.IsLetter(backward)) result.Append(backward); } return result.ToString(); }

Ответ 4



Ну, вот развертка слова наоборот вручную без использования доп.методов с сортировкой, вдруг понадобится private char[] SortArray(char[] arr) { char max = arr[0]; for (int i = 0; i < arr.Length; i++ { max = arr[i]; for (int j = i; j < arr.Length; j++) { if (max < arr[j]) { max = arr[j]; arr[j] = arr[i]; arr[i] = max; } else if (max>='0'&&max<='9') { arr[i] = max; break; } } } return arr; }

Ответ 5



Решение на C++11 с использованием STL: #include #include #include std::string specReverse(const std::string& str) { std::string result(str); for (auto begin = result.begin(), end = result.end() - 1; begin < end; ) { if (!isalpha(*begin)) ++begin; else if (!isalpha(*end)) --end; else std::swap(*begin++, *end--); } return result; } int main() { const std::string input = "a1bcd"; std::cout << "Input=\"" << input << "\", output=\"" << specReverse(input) << "\"." << std::endl; }

Зачем использовать Python2 вместо Python3?

#python #python_2x


Почему некоторые продолжают использовать интерпретатор предыдущей версии, почему
он еще не умер и не забыт?

Третья версия ушла далеко вперед (один async и новый GIL чего стоят), многие библиотеки
были портированы (ранее, например, был повод использовать Py2 - OpenCV, но и ее портировали).

Единственный повод - поддержка старых проектов и невозможность переезда, но по-прежнему
есть те, кто стартует новые проекты на Py2. Новые вопросы на StackOverflow появляются.

Зачем, какие очевидные причины?
    


Ответы

Ответ 1



Очевидной причиной является несовместимость большинства старых рабочих тестированных Питон 2 программ с Питон 3. Даже если большинство изменений тривиально (и может быть автоматизированно), переход на Питон 3 требует наличия тестов и времени программистов, трату которого надо обосновать. Питон 2 сам по себе уже хорошим языком является. Питон 3 местами лучше, но для каких-то задач может даже хуже показаться на первый взгляд. Даже если разработчики могут найти время для перехода на новый язык, учитывая что программисты люди любознательные, Питон 3 может конкурировать с переходом и на другие языки такие как Go, OCaml (Питон 3 несовместим, но он "недостаточно несовместим" если что-то новое хочется попробовать). Изначальной адаптации Питона 3 не помогало, то что первые версии (до Питон 3.2-3.3) не были предназначены для широкого использования. Большинство книг/ресурсов в сети использовали Питон 2 синтаксис. Обычно, предустановленная команда python запускает Питон 2 на POSIX системах. Большинство живых популярных библиотек работают как на Питоне 2 так и 3. Существует "длинный хвост" библиотек, которые только на Питоне 2 работают (публичные и внутренние инструменты). Из-за заявленной долгосрочной (на данный момент до 2020) официальной поддержки Питона 2, люди немного теряют оставаясь на Питоне 2 (хотя люди часто недооценивают время жизни программ). Заставлять программистов учить разницу между текстом, представленным в виде Unicode строк и байтами создаёт заметный барьер для смены версий для нового кода. Особенно, если программист работает в окружении где текст в основном представлен в виде байт, закодированных в utf-8, или хуже: семантически текстовые интерфейсы используют исторически байтовые API на POSIX системах, которые допускают произвольные последовательности байтов (имена файлов, параметры командной строки, переменные окружения), что требует таких вещей как surrogateescape, чтобы продолжить с Unicode работать по умолчанию. Уроки Чтобы не повторять ошибок, можно было бы избежать смены основной версии и вводить новые изменения поэтапно (Python 4 в понимании Python 3 не должно быть): не накапливать много несовместимых изменений, которые нужно научиться использовать и искать способ подружить со старым кодом (низкая стоимость перехода) возможно большинство новых фич убрать под from __future__ import division, print_function, unicode_literals, etc, которая включается через несколько выпусков по умолчанию (позволяет тестировать, преобразовывать код по одному модулю за раз) публиковать на PyPI модули, облегчающие переход с версии на версию, например, contextlib2, pathlib2, subprocess32, etc предоставить возможность исполнять старый код на новой версии без изменений (чтобы старые программы поддерживать—это относительно просто, если другие пункты также реализовать) конвертировать новую версию в старую, чтобы новый код в старом окружении исполнять (новые программы можно было бы на новой версии языка писать, а исполнять в старом окружении) (3to2 вместо 2to3—см. futurize и pasturize скрипты) ограничить поддержку старых версий (как сейчас 3.2, 3.3, 3.4, 3.5 поддерживаются) — только одна официальная текущая версия языка (чтобы ненужный выбор не создавать) использование semver для языка может быть вредно по психологическим причинам: вместо 3.0 можно было 2.6 выпустить с меньшим набором новых фич (изменение основной цифры может пугать без оснований) медленно убирать старые особо зловредные фичи — упомянуть в документации лучший путь, но фактически задержать на несколько лет удаление старого кода (адаптация под каждую новую версию в любом случае может требовать работы—так барьер между перехода на каждую версию не слишком высок) В итоге: люди, которые любят новые блестящие штучки, могут их использовать, не ожидая перехода всей кодовой базы на новую версию люди, которым надо чтоб продолжало работать, также довольны—старый код не должен ломаться (за исключением обычного ожидаемого подкручивания гаек при переходе на новую версию) особо консервативные люди продолжают сидеть на Python 2.4, 2.6 новички просто начинают с текущей единственной версии

Ответ 2



Для меня одной из очевидных причин являются всяческие UNIX/Linux дистрибутивы, где по умолчанию стоит Python2 и у львиной доли простых юзеров нет прав, чтобы поставить Python 3 на уровне системы. Следовательно все их наработки не будут правильно (если специально этим не озаботиться) работать у остальных юзеров на Python 2. Вот когда все популярные дистрибутивы будут выходить с Python 3 по-умолчанию, тогда можно будет постепенно начинать забывать про Python 2, IMO...

Ответ 3



python2 и python3 сейчас одинаково популярны, для python2 продолжают писать библиотеки, улучшать. В чём-то синтаксис python2 лучше чем у python3, удобнее. К примеру print по моему удобнее писать без скобок. для python2 есть модули которых не сделали для python3. Тем более python 2.7 у меня стоял с самого начала, многие не хотят отвыкать от python2 синтаксиса - поэтому на нём работают многие Вообщем одновременно востребованы две параллельно развивающиеся версии языка Python — 2 и 3.

Ответ 4



Неочевидная проблема, об которую сам как-то обжегся: даже если библиотекой заявлена поддержка Python 3, еще неизвестно какого она качества. Например, год-два назад сделал попытку перейти на Py3: нужен был Pyserial, так он глючил на элементарных вещах, при том что с Py2 работал без проблем, пришлось вернуться на Py2. Также в комменте годичной давности на Hacker News, говорилось что есть аналогичная проблема с Machine Learning библиотеками: есть поддержка Py3, но они забагованнее и поэтому народ все равно использует Py2. В комменте (март 2016) к статье мейнтейнер библиотек говорит что баги проявляющиеся на Py3 месяцами висят, потому что все на Py2. Оригинал: "A trove classifier says nothing about the quality of running a polyglot library on Python 2 or Python 3. I say this as someone who maintains polyglot libraries where I’ve had Python 3 bugs persist for months, because everyone actually uses Python 2." https://blogs.msdn.microsoft.com/pythonengineering/2016/03/08/python-3-is-winning/

Стилизировать первые 3 символа в тексте на css

#javascript #jquery #css #вёрстка


Как на js или css стилизировать первые 3 символа в тексте? Нужно их скрыть или сделать
прозрачными.

  • 1. Анкор (41)

  • Ответы

    Ответ 1



    Ну коли можно пользоваться скриптами теперь, то: Вариант на jq: $('input').on('click', function() { $('.cat-item a').each(function() { var text = $(this).text(); text = '' + text.substr(3, text.length); $(this).html(text); }) });
  • 1. hello!
  • 2. this
  • 3. is
  • 4. a test!


  • Ответ 2



    $(function() { var text, textBefore, textAfter; $('ul li').each(function() { text = $(this).text(); textAfter = text.substring(3); textBefore = text.substring(0,3); $(this).empty().append('' + textBefore + '').append(textAfter); }); }); ul span { opacity: .3; }
    • 1. Anchor
    • 2. Anchor
    • 3. Anchor


    Ответ 3



    Решение на чистом JS для скрытия первых трёх символов: var first = document.querySelector('.cat-item-15 a').innerHTML.substr(0,3); var second = document.querySelector('.cat-item-15 a').innerHTML.substr(3); document.querySelector('.cat-item-15 a').innerHTML = '' + second; span.hidden { visibility: hidden; }

    Ответ 4



    Через css вы не сможете подсчитать количество букв(символов) тем самым вы не сможете дать стили, через css вы сможете прописать стили только первому элементу элемент::first-letter. Для решения вашей проблемы необходимо заранее (например через php) вырезать первые 3 символа и вставить в отдельный контейнер для дальнейшего стилизирования.

    Ответ 5



    Возможно так: .t2 { color: red; }

    спрятать первые 3 символа в тексте

    Стилизировать первые 3 символа в тексте



    Ответ 6



    Нечего везде пихать js. li { color: red; } span { color: black; }
    1. Анкор (41)
    2. Анкор (41)
    3. Анкор (41)
    4. Анкор (41)


    Ответ 7



    Если речь именно о списках, то всего-навсего list-style-type:none. См дополнительно http://htmlbook.ru/content/svoystva-spiskov

    Как подключить ADB WIFI в Android Studio?

    #android #android_studio #gradle #wifi

    
    Скачал плагин ADB WIFI для запуска приложения через WIFI. При нажатии на Tools, ADB
    to WIFI ничего не происходит. Как его подключить?
        
    


    Ответы

    Ответ 1



    Если не пользоваться плагинами, которые будут работать через раз то можно и руками всё сделать. Там всего пара действий и плагин тут не очень нужен. Подключаем девайс по USB Открываем терминал в папке с adb по пути ПУТЬ_ДО_SDK/sdk/platform-tools Убеждаемся что девайс и комп в одной Wi-Fi сети. Набираем adb tcpip 5555 Набираем adb connect IP_ДЕВАЙСА Далее, в 95% случаев достаточно выполнить лишь п5.

    Ответ 2



    Если вы про этот плагин, то для того чтобы подключить устройство по wi-fi, его необходимо хотя бы раз подключить с помощью провода. Об этом сказано здесь.

    Ответ 3



    Немного сейчас не так. Эта инструкция должна помочь. 4 шага: Подключаем девайс по USB В терминале: cd C:\Users\mxsof\AppData\Local\Android\Sdk\platform-tools adb tcpip 5555 adb connect ЛОКАЛЬНЫЙ_IP_ДЕВАЙСА:5555 Примечания: Девайс и компьютер должны быть в одной Wi-FI сети. Как найти путь к platform tools: Settings > вбиваем в поиск "android sdk", копируем путь, у меня это C:\Users\mxsof\AppData\Local\Android\Sdk, добавляем к пути \platform-tools. Посмотреть ваш локальный ip-адрес можно в настройках в разделе о телефоне, или воспользовавшись любым онлайн сервисом.

    Помогите с dasharray и dashoffset

    #css #css3 #svg

    
    Никак не могу понять как правильно выставить stroke-dasharray и stroke-dashoffset.
    у меня результат на картинке сверху, снизу показано как нужно, и различия наложения(
    позиция чуть не та (нужно больше против часовой, и визуально нужно чуть больше оранжевого
    и меньше томатного цвета) никак не могу осознать что нужно вбить  
    
    
    
      
    
      
    
      
    
      
    
      
    
    
    
    svg {
      border: 1px solid #dddddd;
    }
    
        
    


    Ответы

    Ответ 1



    Посмотрите примеры c stroke-dasharray, совсем немного строчек кода: Анимация бордюра из средней точки Весь секрет действия в этой строчке: attributeName="stroke-dasharray" from="0 152.2 0 152.2" to="0 0 304.4 0" Трафарет лоадера с бегунком Всё действие в этой строчке: Пример реализации stroke-dasharray с помощью JS Пример универсального решения, когда изменяя значения переменных в скрипте можно получить любое количество сегментов на окружности Анимация CSS начинается после наведения курсора const SVG_NS = 'http://www.w3.org/2000/svg'; let R = 40; let perimeter = 2*Math.PI*R let dash = .8*perimeter/6; let gap = .2*perimeter/6; let dasharray = document.createElementNS(SVG_NS, 'circle'); dasharray.setAttributeNS(null, "r", R); dasharray.setAttributeNS(null, "stroke-dasharray", `${dash}, ${gap}`); svg.appendChild(dasharray); circle { stroke-width:20px; stroke:purple; fill:transparent; } circle:hover { stroke:dodgerblue; -webkit-animation: rotate 6s linear infinite; animation: rotate 6s linear infinite; } @-webkit-keyframes rotate { 100% {-webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg);} } @keyframes rotate { 100% {-webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg);} } Это всё лирика, вернемся к практике. Вопрос автора в итоге - разбивка окружности на равные сектора и расположение одного из секторов относительно вертикальной координаты. На видимый конечный результат влияют четыре фактора: Радиус окружности stroke-dashoffset - сдвиг начала линии. Чтобы исключить его влияние установим stroke-dashoffset="0" Положение начальной точки, именно от неё будет рисоваться первый сектор прерывистой линии. Для окружности это положительная ось "Х". Чтобы отсчет вести от вертикальной линии, повернем окружность против часовой стрелки на 90 градусов. transform=" rotate(-90 175 175)" stroke-dasharray Как всё же просчитать параметры Stroke-dasharray? stroke-dasharray="30 35" "30" - длина черточки, "35" длина пробела. При равенстве значений можно писать только одну цифру. stroke-dasharray="30 35 30 5" Две пары значений, как в примере с бордюром см. выше В этом случае - Длина черты - длина пробела - длина черты - длина пробела Подробнее здесь, здесь и здесь Два сектора Допустим нам надо разбить круг на два равных сектора. Первый сектор займет черта, второй сектор - пробел. Длина всей окружности при радиусе = 50px составит с=2 х 3.14 х 50 = 314 px. Длина сектора = 157px или 180° stroke-dasharray="157 157" Развертка окружности в линию Ручка к мишени Блок цветных кругов Начальная метка stroke-dashoffset Поясняющий текст Circle / "2" Line stroke-dasharray="157 157" circle - "darkorange" stroke-dasharray="157 157" stroke-dashoffset="0" Линии (grey) проходящие через центр полотна SVG Линия длиной 314px над кругом,- это развертка круга с длиной окружности -314px Цветные точки - начальные точки рисования. На окружности от начальной точки по часовой стрелке отрисован первый сектор - (черта stroke-dasharray) - оранжевого цвета и второй сектор томатного цвета это,- пробел stroke-dasharray Вверху по линии от начальной точки, первый оранжевый сектор - черта, томатный отрезок - пробел. Три сектора Длина сектора = 314 / 3 = 104,7 или 120° stroke-dasharray="104.7 104.7" Развертка окружности в линию Ручка к мишени Блок цветных кругов Начальная метка stroke-dashoffset Поясняющий текст Circle / "3" Line stroke-dasharray="104.7 104.7" circle - "darkorange" stroke-dasharray="104.7 104.7" stroke-dashoffset="0" Линии (grey) проходящие через центр полотна SVG Я не случайно добавил в примерах линию длиной равную длине окружности. Без неё уже был бы непонятен результат. Ожидали увидеть три сектора окружности одной длины, а получили два сектора, разной длины. Сейчас понятно, что два соседних сектора окружности сомкнулись. Четыре сектора Длина сектора = 314 / 4 = 78,5 или 90° stroke-dasharray="78.5 78.5" Развертка окружности в линию Ручка к мишени Блок цветных кругов Начальная метка stroke-dashoffset Поясняющий текст Circle / "4" Line stroke-dasharray="78.5 78.5" circle - "darkorange" stroke-dasharray="78.5 78.5" stroke-dashoffset="0" Линии (grey) проходящие через центр полотна SVG Здесь всё просто,- каждый сектор занял свою четверть окружности (90°) Две черты и два пробела stroke-dasharray Шесть секторов Длина сектора = 314 / 6 = 52,3 или 60° stroke-dasharray="52.3 52.3" Развертка окружности в линию Ручка к мишени Блок цветных кругов Начальная метка stroke-dashoffset Поясняющий текст Circle / "6" Line stroke-dasharray="52.3 52.3" circle - "darkorange" stroke-dasharray="52.3 52.3" stroke-dashoffset="0" Линии (grаy) проходящие через центр полотна SVG Начал проясняться алгоритм для секторов с равными промежутками,- Удваиваем количество закрашенных секторов, находим длину одного сектора и подставляем в stroke-dasharray Проверяем на примере автора вопроса. Надо 5 закрашенных секторов итого вместе с равными промежутками нужно делить длину окружности на 10 частей. 10 секторов Длина дуги сектора = 314 / 10 = 31,4 или 36° stroke-dasharray="31.4 31.4" Линии повторяющая расцветку двух кругов Ручка к мишени Блок цветных кругов Начальная метка stroke-dashoffset Поясняющий текст Circle / "10" Line stroke-dasharray="31.4 31.4" circle - "darkorange" stroke-dasharray="31.4 31.4" stroke-dashoffset="0" Линии (grey) проходящие через центр полотна SVG Нам нужно повернуть против часовой стрелки верхний оранжевый сектор, чтобы вертикальная линия делила его по середине. Можно сделать это двумя способами: Повернуть на 108° градусов против часовой стрелки оранжевый круг. Расчет: В крайнем примере у нас уже повернуто на 90° градусов и доворачиваем до середины сектора ещё 18° градусов (весь сектор 36°) итого: Вариант с поворотом сектора Ручка к мишени Блок цветных кругов Начальная метка stroke-dashoffset Поясняющий текст Circle / 10 transform="rotate(-108 175 175)" circle - "darkorange" stroke-dasharray="31.4 31.4" stroke-dashoffset="0" Линии (grey) проходящие через центр полотна SVG Вариант с отступом Во всех предыдущих примерах мы имели нулевой отступ и начало сектора совпадало с вертикальной линией. Теперь, чтобы сдвинуть сектор на половину его дуги = 31.4 / 2 = 15.7 Используем - stroke-dashoffset="15.7" Ручка к мишени Блок цветных кругов Начальная метка stroke-dashoffset Поясняющий текст Circle / 10 stroke-dashoffset="15.7" circle - "darkorange" stroke-dasharray="31.4 31.4" stroke-dashoffset="15.7" Линии (grey) проходящие через центр полотна SVG Решение вопроса автора stroke-dasharray="31.4 31.4" и stroke-dashoffset="31.4" Вот если бы я сразу дал такой ответ, что вам нужно вбить? Это помогла бы? Да, но один раз, и следующая подобная задача вызвала бы без знания теории точно такие же мучения, как были с первым примером. Не поленитесь, прочитайте пожалуйста "много буков" выше.

    Ответ 2



    Хотелось ещё добавить информации по анимации, вдруг кому-нибудь она будет полезна и подвигнет сделать на основе примеров, что-то своё.* Вращение по часовой стрелке В пример "10 секторов" из первого ответа добавлена всего одна команда, реализующая вращение по часовой стрелке: Ниже полный код: Линии повторяющая расцветку двух кругов Блок цветных кругов Начальная метка stroke-dashoffset Линии (grey) проходящие через центр полотна SVG Вращение против часовой стрелки Обратите внимание, сравнивая с первым примером анимации,- в атрибуте анимации "values" параметры 314;0 поменялись местами. Линии повторяющая расцветку двух кругов Блок цветных кругов Начальная метка stroke-dashoffset Линии (grey) проходящие через центр полотна SVG Вращение в обе стороны с паузой Пауза достигается повторением начальных и конечных значений stroke-dashoffset Линии повторяющая расцветку двух кругов Блок цветных кругов Начальная метка stroke-dashoffset Линии (grey) проходящие через центр полотна SVG

    Разница между okhttp и retrofit

    #java #android #retrofit #okhttp

    
    Доброго времени суток. Кто-нибудь может объяснить мне разницу между retrofit и okhttp?
    Ведь в okhttp строить запросы гораздо легче, на мной взгляд, тогда почему все используют
    retrofit?
        
    


    Ответы

    Ответ 1



    Retrofit по сути это обертка для OkHttp или как привычно слышать API. И действительно это и есть REST API. OkHttp - это клиент HTTP / SPDY. Отсюда разница: Для OkHttp мы формируем URL, делаем запрос, получаем объект. А вот Retrofit генерирует URL, по уже заданным правилам и это действительно очень удобно. Всё что нужно это прописать интерфейс. После получения объекта в ретрофит можно использовать парсер(можно написать свой), который может сразу предоставить объект в нужном виде в колбеке для последующей работы, тоже удобно. Те по факту Retrofit всеравно использует okHttp, для того чтоб осуществить запрос, просто он дополнительно предоставляет дополнительный функционал и довольно удачно. По скорости работы всё будет идентично и это очевидно. А вот удобства для структуры очень много, Retrofit хорош для RxAndroid и удобно встает в Clean Architecture, удобно использовать в MVP, очень удобно выносится в модуль Dagger2. Да и сам Retrofit не ограничивает в теории настройку клиента OkHttp, вы можете его подменить.

    Ответ 2



    okhttp это библиотека, которая реализует связь по http. Retrofit это библиотека, которая даёт вам удобную работу с REST сервисами. Объясняю: По умолчанию ретрофит базируется на Okhttp. Т.е. вам как разработчику, использующему ретрофит необходимо написать всего один интерфейс, и потом Retrofit.Bulder() сам сгенерирует для вас реализацию. Внутри сгенерированного класса вы увидите код работающий на OkHttp. Можно работать и без ретрофита, но тогда вместо написания одного интерфейса вам придется писать очень много лишнего кода. Короче говоря, Ретрофит это обертка над OkHttp + куча разных крутых фишек, типа сериализаторов (к примеру Gson подключается одной строкой и все ваши Java классы магическим образом сериализуются/десериализуются в JSON) можно и в XML, еще из фишек - адаптеры, к примеру для RxJava и других хитрых библиотек, как упоминалось ранее - кодогенерация. Вы не пишете тонны кода, Ретрофит сгенерирует их за вас. Ну и прочие приятные фишки, которые вы откроете для себя плотно нырвнув в изучение ретрофита и okhttp

    Ответ 3



    Retrofit суть надстройка над OkHttp. Она помогает писать меньше кода для составления запросов к API и делать это в едином стандарте - вы в отдельном интерфейсе определяете java методы, указывая аннотациями тип http метода и его параметры - адрес, заголовки, поля, тело. Также вы определяете там тип возвращаемого значения - например класс-модель, в которую распарсится json ответ от сервера. После чего создаёте экземпляр класса, реализующий этот интерфейс (весь код уже готов) и просто вызываете описанный в интерфейсе метод - он вернёт ответ сервера в виде экземпляра java класса. Как итог - меньше кода и всё собрано компактно в одном файле.

    Стоит ли продолжать начинания в изучении Python как основного? [закрыт]

    #python #python_3x

    
            
                 
                    
                        
                            
                                Закрыт. На этот вопрос невозможно дать объективный ответ.
    Ответы на него в данный момент не принимаются.
                                
                            
                        
                    
                                
                                    
                    
                            
                                
                            
                        
                            
                                Хотите улучшить этот вопрос? Update the question so it
    can be answered with facts and citations by editing this post.
                            
                            Закрыт 1 год назад.
                                                                                    
               
                    
            
    Мне симпатизирует синтаксис, но язык кажется каким-то больше вспомогательным сам
    по себе. Да, есть фреймворки, но тот же Джанго относительно не столь популярен. Но
    на данный момент это единственный язык, который я знаю на начальном уровне, и стоит
    ли продолжать?
    
    Не хочу ситуацию, чтоб я остался на улице, а PHP/C++/Java-элита бы пожинала плоды. 
        
    


    Ответы

    Ответ 1



    1. Мнение Python — не «вспомогательный» язык, это популярный язык программирования, продолжать изучение стоит, на улице при соответствующем уровне знаний не останетесь. 2. Аргументация 2.1. Рейтинги популярности языков программирования PYPL — второе место на февраль 2018; Redmonk — третье место на июнь 2017; TIOBE — четвёртое место на январь 2018; Trendy Skills — пятое место на февраль 2018. Правда, на 4-м месте в этом рейтинге HTML, не являющийся языком программирования. 2.2.Рейтинги востребованности рабочих мест Indeed — 2-е место на ноябрь 2017; Indeed другая статистика — 4-е место на декабрь 2017. 2.3. Рейтинги языков программирования по зарплате разработчиков ChallengeRocket — 3-е место на февраль 2017. См. также перевод отрывка, посвящённого Python: Это универсальный и понятный язык, используемый крупными игроками в технологической индустрии (Google, NASA). Принимая во внимание, что уже в 2016 инженер-программист со знанием Python может заработать до $100 000, мы прогнозируем, что годовой оклад Senior Python Developer будет колебаться вокруг суммы $105 000 и выше. Это объясняется в значительной степени популярностью языка и его частым появлением в списках требований в процедурах найма на работу. Согласно рейтингу TIOBE, Python находится на 5-м месте по количеству запросов в основных поисковых системах, поэтому аналитики предполагают, что его популярность будет продолжать расти. За последние 5 лет популярность Python демонстрировала наибольшие темпы роста в этом аспекте (6,8%, когда, например, PHP имеет -5,0%). 3. Дополнительная информация О том, как вычисляются рейтинги, в большинстве случаев можно посмотреть по ссылкам на эти рейтинги. См. также: Краткое описание, какие критерии берутся в расчёт для некоторых из перечисленных выше рейтингов.

    Ответ 2



    Хороший специалист не останется на улице, независимо от того, в какой именно области он специалист. А плохой не сможет "пожинать плоды" даже используя самый популярный и востребованный язык.

    Ответ 3



    Если ты думаешь что python из-за своей простоты(более менее читаемый код это его преимущество) язык для начинающих и особой пользы не несет то ты ошибаешься. Во первых Google использует питон в своей поисковой системе, компания irobot использует питон для разработки коммерческих военных роботов. Также Pixar, intel, IBM, cisco, NASA, JBL и другие компании используют питон для разных задач. Я бы не сказал что python вспомогательный язык программирования. Да для большинства робот в компаниях тебе понадобятся и другие языки программирования(ибо я пока ещё не нашёл компанию там где надо было знать всего лишь один пайтон). Но все же python как для начала так и для будущего надо выучить.

    Ответ 4



    Судя по моим наблюдениям, количество Python-вакансий растет, особенно, если связаться с такими областями как Data Mining или Deep Learning. Сейчас там Python и R прямо правят бал. Так что врубайтесь в питон посильнее и получше и вперед! Без куска хлеба с икрой не останетесь. Кроме того, если по-хорошему освоить Python и понять как вообще работает программирование, то остальные языки пойдут полегче.

    Заменить три блока if…else на более эстетичную запись

    #javascript #if

    
    Есть функция, которая принимает необязательный параметр: любое число. Все работает
    норм, пока это число !=0
    
    
    function go(number){
        let x = number || 10;
        console.log(x);
    }
    go()// вернет 10;
    go(20)// вернет 20;
    go(0)// вернет 10, а нужен 0;
    
    
    
    
    Проблема решается с помощью конструкции if..else..else, но для такой простой функции
    это слишком громоздко. Можно ли переписать как-то более эстетично?
        
    


    Ответы

    Ответ 1



    Попробуйте такой вариант: function go(number){ let x = number || number === 0 ? number : 10; console.log(x); } go()// вернет 10; go(20)// вернет 20; go(0)// вернет 0;

    Ответ 2



    Можно воспользоваться уже доступными: параметрами по умолчанию function go(number = 10) { console.log(number); } go() // вернет 10; go(20) // вернет 20; go(0) // вернет 0;

    Метод ForEach и IEnumerable

    #c_sharp #net #linq #дизайн_языка

    
    Подскажите, а в чем мотивация того, что этот метод работает только с List? Ведь
    IEnumerable тоже имеет все необходимое.
        
    


    Ответы

    Ответ 1



    Многие люди спрашивают меня, почему Microsoft не сделал для коллекций метод расширения ForEach. У класса List уже есть такой метод, но почему не добавить такой метод для всех последовательностей. Практически - это однострочник: public static void ForEach(this IEnumerable sequence, Action action) { // argument null checking omitted foreach(T item in sequence) action(item); } Обычно на вопрос: "Почему X не реализовано?" я отвечаю, что любая особенность не реализована, пока кто-то ее не спроектирует, реализует, протестирует, и предоставит. И никто не даст денег на это. И да, хотя я отмечал, что даже самые маленькие особенности могут иметь большую стоимость, конкретно эта по настоящему простая, очевидная, легко тестируемая и легко документируемая. Стоимость всегда имеет значение, но в этом случае она незначительна. С другой стороны, если это так просто, почему бы не сделать это самому, если так нужно? И по настоящему важна тут не низкая стоимость, а полученная выгода. Дальше будет видно, что я считаю выгоду здесь также небольшой, если вообще не отрицательной. Но мы должны посмотреть немного глубже. У меня есть две причины против этого метода. Первая причина заключается в том, что это нарушает принципы функционального программирования, на которых основаны остальные операторы для последовательностей. Очевидно, что цель этого метода - вызвать побочные эффекты. Цель выражения (expression) - вычислить значение, а не получить побочный эффект. Получение побочного эффекта - это цель для statement. Его вызов выглядит как выражение (expression) (хотя, надо признать, что, так как метод возвращает void, выражение может быть использовано только в контексте "statement expression"). Меня не устраивает делать единственный оператор только для последовательностей, который будет использоваться только для побочных эффектов. Вторая причина заключается в том, что это ничего не добавляет языку. И сделав это можно будет переписать совершенно чистую строку кода foreach(Foo foo in foos){ statement involving foo; } в следующую foos.ForEach((Foo foo)=>{ statement involving foo; }); которая использует почти те же символы в немного другом порядке. Кроме того, вторая версия тяжелее для понимания, отладки, вводит семантику замыканий, что в некоторых случаях может поменять время жизни объекта. Когда мы предоставляем два похожих способа сделать одно и то же, мы вносим путаницу в индустрии, становится тяжелее читать код друг друга и т.д. Иногда выгода от наличия двух разный текстовых представлений для одной операции (например, query-синтаксис vs method-синтаксис или + vs String.Concat) настолько огромна, что можно пренебречь потенциальной путаницей. Но убедительное преимущество query выражений - их читаемость; новая форма foreach читается определенно не лучше, а может быть даже и хуже. Если вы не согласны с такими философскими возражениями и видите практическую ценность в таком шаблоне, идите и напишите этот однострочник сами. Перевод блога @EricLippert

    Ответ 2



    Этот метод нужен только для side-эффектов, что противоречит функциональной концепции linq. Этот метод не ведёт к сокращению кода: foreach(Foo foo in foos){ statement involving foo; } foos.ForEach((Foo foo)=>{ statement involving foo; }); получились почти те же символы, но в несколько другом порядке. К тому же вторую версию сложнее понять, сложнее отладить и в ней появляется замыкание, которое может повлиять на время жизни объектов. Но каждый, кто не согласен с этими философскими причинами и видит пользу в этом паттерне, - вперёд! Просто реализуйте этот тривиальный однострочник самостоятельно. Источник: https://blogs.msdn.microsoft.com/ericlippert/2009/05/18/foreach-vs-foreach/

    Ответ 3



    До .net 4.5 разница была во внутренней реализации: foreach внутри реализовался(и реализуется) через итератор. Это означает что все завалится как только убрать из списка один элемент. Зато работает быстрее. ForEach() же БЫЛ внутри реализован через for(int i=0; i { if(x.RemoveMe) someList.Remove(x); }); Начиная с .net 4.5 оба метода работают через итератор и являются взаимозаменяемыми. Просто разный синтаксис использования. Информация взята с: https://stackoverflow.com/a/226082/4423545 Так же нашлась статья Eric Lipperts blog "foreach" vs "ForEach" -- а он -- principal developer on the C# compiler team. Думаю, что там можно нарыть какую-то дополнительную информацию. На сколько я понял, ForEach оставили только листу и не привязывали всем IEnumerable что бы не плодить: foos.ForEach((Foo foo) => { statement involving foo; }); // сложно для понимания при беглом взгляде а что бы люди писали: foreach(Foo foo in foos) { statement involving foo; }// легко для понимания И даже в 1 строку читается все равно проще: foreach(Foo foo in foos){ statement involving foo; }

    Русский язык в исходном коде в Dev C++ [дубликат]

    #windows #cpp

    
            
                 
                    
                        
                            
                                This question already has answers here:
                                
                            
                        
                    
                            
                                Русский язык в консоли
                                    
                                        (4 ответа)
                                    
                            
                                    Закрыт 3 года назад.
                
                        
    Я недавно начал изучать С++, у меня есть компилятор Dev C++. Когда я делаю 
    
    std::cout<<"Привет!"; 
    
    
    то получается абракадабра! А если перебираю символы циклом, то русские буквы отображаются
    правильно. Я думаю проблема в различии кодировок dos и windows. Кто знает какие-нибудь
    примочки для Dev C++ (типа keycyr для pascal) или операторы/функции/процедуры C++ позволяющие
    сменить кодировку std::cout.
        
    


    Ответы

    Ответ 1



    С setlocale() по науке правильно, но если локализация кривовата (как у меня на этой машине), то не работает. В Windows есть 2 функции, CharToOem(char, char) и OemToChar(char, char) для перевода cp-1251 в cp-866 (консоль) и обратно. Пример: #include #include #include #include main () { char str[1000], buf[1000]; int itty = isatty(fileno(stdin)), otty = isatty(fileno(stdout)); strcpy(str, "привет"); if(otty) CharToOem(str, str); puts(str); fgets(str, 1000, stdin); if (itty) OemToChar(str, str); str[strlen(str) - 1] = `\0`; if (strstr("привет", str)) strcpy(buf, "да, часть от 'привет'"); else strcpy(buf, "такого нет в слове 'привет'"); if(otty) CharToOem(buf, buf); puts(buf); } В программе набрано в cp-1251 (она же ANSI). При вводе с консоли, независимо от setlocale() придется переводить кодировку. Также обратите внимание, что параметры командной строки, набранные в консоли поступают в программу в кодировке cp-1251!!! Кодировка в файлах обычно подразумевается в cp-1251, это надо учитывать при переадресации (>) вывода (stdout, stderr). Я продемонстрировал в примере, как это можно делать. UPDATE @insolor дал замечательный ответ как правильно программировать работу с русскими буквами в консоли Windows, используя стандартные функции SetConsoleCP(1251) и SetConsoleOutputCP(1251). В обсуждении (комментариях) к его ответу можно найти различные детали, в частности установку русского шрифта. Похоже его ответ прошел незамеченным для некоторых участников форума. Поэтому я решил привести функцию, вызов которой в самом начале упрощает программирование ввода/вывода русских букв в Windows и пример ее использования. cons1251.c #include static int oldin = 0, oldout = 0; static void exitfunc() { SetConsoleCP(oldin); SetConsoleOutputCP(oldout); } void cons1251 () { if (oldin) return; atexit(exitfunc); oldin = GetConsoleCP(); oldout = GetConsoleOutputCP(); SetConsoleCP(1251); SetConsoleOutputCP(1251); } rustest.c #include // русский текст в кодировке cp1251 (она же ANSI) // обратите внимание, не нужен main() { printf ("This is russian [аБвГдЕ] before cons1251()\n"); cons1251(); printf ("This is russian [аБвГдЕ] after cons1251()\n"); char str[1000], buf[1000]; printf ("Привет - введи часть от \"привет\"\n"); fflush(stdout); fgets(str,1000,stdin); str[strlen(str)-1] = 0; printf("Вы ввели: '%s'\n",str); if(strstr("привет",str)) printf("да, часть от 'привет'\n"); else printf("такого нет в слове 'привет'\n"); fflush(stdout); puts("ждем ввода to exit..."); fflush(stdout); fgets(str,1000,stdin); } Вызов fflush(stdout) при работе с консолью (tty) необязателен, однако для вывода в некоторых эмуляторах терминала (например в Emacs eshell) необходим. Это пример компиляции (Windows 7, Emacs eshell) окно в cp1251 поэтому вывод русского текста и до и после cons1251() одинаковый (и правильный). c:/Users/avp/src/cc/hashcode $ gcc -c cons1251.c c:/Users/avp/src/cc/hashcode $ gcc rustest.c cons1251.o -o rustest c:/Users/avp/src/cc/hashcode $ ./rustest This is russian [аБвГдЕ] before cons1251() This is russian [аБвГдЕ] after cons1251() Привет - введи часть от "привет" иве Вы ввели: 'иве' да, часть от 'привет' ждем ввода to exit... c:/Users/avp/src/cc/hashcode $ c:/Users/avp/src/cc/hashcode $ К сожалению для стандартного cmd-окошка Copy/Paste не работает, так что попробуйте сами. Для окна с PowerShell в Win 7 этот метод к сожалению не работает (в отличие от «геморройного» CharToOem/OemToChar). Надеюсь этот текст окажется кому-то полезным. UPDATE 2 (for @Rules) Исходный файл tt.cpp #include extern "C" void cons1251(void); main() { std::cout << "Привет, введите слово\n"; cons1251(); std::cout << "Привет, введите слово\n"; char str[100]; std::cin >> str; std::cout << "Вы ввели: " << str << std::endl; } c:/Documents and Settings/avp/src/hashcode $ g++ tt.cpp cons1251.o -o tt c:/Documents and Settings/avp/src/hashcode $ ./tt Привет, введите слово Привет, введите слово йцукен Вы ввели: йцукен c:/Documents and Settings/avp/src/hashcode $ Пример вывода из эмулятора терминала Emacs eshell. Поэтому первый «Привет...» тоже состоит из нормальных букв. В обычной консоли там «кракозябры», а дальше нормальная кириллица. Обращаю особое внимание. Перед запуском надо изменить шрифт в консоли на Lucida Console. Иначе будут кракозябры (но другие). Для замены шрифта кликаете правой кнопкой на надписи «Командная строка» окна консоли. В открывшемся меню выбираете «Свойства». В появившемся окне выбираете вкладку «Шрифт» и там выбираете «Lucida Console». Потом подтверждаете, что попросит. Если при подтверждении выбрать пункт «Изменить ярлык для запуска этого окна», то новые окна командной строки будут уже с нужным шрифтом. Вроде все.

    Ответ 2



    Можно сразу редактировать исходник в кодировке cp866, для этого нужен любой редактор, поддерживающий эту кодировку. Например, можно редактировать во встроенном редакторе far manager. В мейне вставляем вызовы двух функций: SetConsoleCP(1251); SetConsoleOutputCP(1251); и при первом запуске устанавливаем шрифт консоли на Lucida Console или Consolas.

    Ответ 3



    Вам необходимо сменить кодировку локали через функцию setLocale(): setlocale(LC_ALL,"Russian"). Более подробное описание: setlocale.

    Ответ 4



    Интересно, а почему бы просто не использовать русскую локаль(?): ... #include ... int main() { setlocale(LC_ALL,"Russian"); // русская локаль }

    Ответ 5



    Русский язык в исходном коде в Dev C++ К среде разработки и компилятору это не имеет никакого отношения. Этот вопрос достаточно распространён. Зачем задавать его лишний раз, если он легко гуглится? Вот некоторые ссылки: Как вывести в консоль русские буквы? Проблема с русским в Visual Studio 2005 (c++)

    Расположение нескольких div-ов в одну строку

    #html #css

    
    Подскажите, пожалуйста, как можно расположить несколько div-ов в одну строку таким
    образом, чтобы даже в том случае, если их общая ширина превышала ширину контейнера,
    они всё равно не переносились на новую строку, а просто происходила обрезка не помещающихся
    div-ов.
        
    


    Ответы

    Ответ 1



    Есть много вариантов, в зависимости от того, как нужно отображать сами блоки. Один с вариантов: .container{overflow:hidden;width:200px} .box{white-space:nowrap} .box div{width:90px;display:inline-block;border:1px solid black}
    content1
    content2
    content3
    Пример

    Ответ 2



    .
    content
    content
    content++


    Ответ 3



    На мой взгляд, самое нормальное решение:
    content
    content
    content++


    Ответ 4



    Я использовал у себя эту часть:
    content
    content
    content++
    и все заработало.

    Си. Условные операторы в макроопределении препроцессора. Возможно ли?

    #c #препроцессор

    
    Нужно исключить отладочные printf() из программы, применяя константу препроцессора.
    Обрамлять каждый вызов printf()
    
    #if DEBUG == 1
    printf();
    #endif
    
    
    не хочется. Можно ли сделать что-то типа:
    
    #define printf(x,y) (if DEBUG == 1 printf(x,y) endif)
    
    
    #if внутри макроопределений запрещены. Есть ли альтернатива?
        
    


    Ответы

    Ответ 1



    Можно определять макрос по разному в зависимости от значения DEBUG: #if DEBUG==1 #define printf_d(...) printf(__VA_ARGS__); #else #define printf_d(...) #endif Но лучше сделать это немного по другому, проверяя не значение, а факт наличия макроопределения: #ifdef DEBUG // . . . Такой подход позволяет включить режим отладки простым указанием имени проверяемого макроса в Make-файле или даже в параметрах команды сборки.

    Ответ 2



    Объявите разные версии макроса PRINT - для отладки и обычную #ifdef _DEBUG #define PRINT(x,y) print(x,y) #else #define PRINT(x,y) #endif

    Ответ 3



    Вот прям не знаю даже, какому из 2-х вариантов (@kff или @gbg) отдать предпочтение: в обоих что-то да не нравится, вот такой нравится: #ifdef _DEBUG #define PRINT(...) print(__VA_ARGS__) #else #define PRINT(...) #endif его и использую, а вот вместо _DEBUG тут лучше использовать любой другой флаг, чтобы отладочную печать можно было включить, независимо от глобальной оптимизации. На самом деле, я часто использую немного другую схему: у меня есть разные версии PRINT, с разными префиксами, чтобы можно было логику вывода на печать детализировать на разных уровнях: #ifdef ENABLE_PRINT #define PRINT(...) print(__VA_ARGS__) #else #define PRINT(...) #endif #ifdef ENABLE_VERB_PRINT #define VERB_PRINT(...) print(__VA_ARGS__) #else #define VERB_PRINT(...) #endif ... А в коде - уже расставляем версии PRINT'ов, в зависимости от логики работы функций: void myFunc(){ VERB_PRINT("func: %s", __FUNCTION__); ... if( !... ){ PRINT("error:%...", ...); } ... } Теперь, можно не меняя код, управлять детализацией логирования, добавляя соответствующие флаги для препроцессора.

    В чем разница между двумя циклами for: при удалении элементов во время обхода списка

    #python #циклы #list #список #python_internals

    
    Почему интерпретатор в первом случае убирает только 3 нуля ['1', '0', '0', '0'],
    а во втором удаляет полностью, в чем разница? For - работает с каждым итерируемым объектом
    по очереди, почему он пропускает 3 нуля?
    
    list1 = ['1', '0', '0', '0', '0', '0', '0', '0', '0', '1']
    for _ in list1:
        list1.remove('0') 
    print(list1)
    
    nuly = ['3', '2', '0', '0', '3', '5', '0', '0', '0', '8', '0'] 
    for _ in nuly:
        nuly.remove('0')
    print(nuly)
    
        
    


    Ответы

    Ответ 1



    Оба цикла одинаковые. Только входные списки разные. Вы удаляете элементы из списка, одновременно обходя его. При обходе списка, цикл for не копирует его, а создаёт итератор, который элементы из списка по одному возвращает. Поэтому когда вы удаляете элемент (.remove('0') ищет один '0' в списке и удаляет его), то список изменяется и эти изменения видны в итераторе. В текущей реализации СPython, итератор списка хранит ссылку на сам список и текущий индекс в нём. Элементы возвращаются пока длина списка больше текущего индекса. Вот суть next(list_iterator) вызова, возвращающего следующий элемент на каждой итерации: listiter_next(listiterobject *it) { ... if (it->it_index < PyList_GET_SIZE(it->it_seq)) { item = PyList_GET_ITEM(seq, it->it_index); ++it->it_index; return item; } ... } Что на Питоне выглядит как: if i < len(lst): item = lst[i] i += 1 return item Если по шагам выполнить код на pythontutor.com: #XXX BROKEN lst = [0, '0', '0', '0', '0', '0', '0', '0', '0', 9] for i, x in enumerate(lst): lst.remove('0') size = len(lst) print(lst) # -> [0, '0', '0', '0', 9] Можно увидеть, что цикл продолжается до тех пор пока i < size. Поэтому цикл может завершиться до того как все '0' элементы удалены. Если вы хотите удалить '0' из списка, то обычный способ: lst[:] = [x for x in lst if x != '0'] Если не создавать временный список, то можно, обходя список, переносить значения, которые хочется оставить в начало списка, а затем удалить все элементы в конце: def remove_all(seq, value): pos = 0 for item in seq: if item != value: seq[pos] = item pos += 1 del seq[pos:] remove_all(lst, '0') Оба решения линейные—O(n). Первое решение требует O(n-k) дополнительной памяти, где k = lst.count('0'). Если известно, что в большом списке, только несколько значений нужно удалить (k маленькое и не зависит от n), то можно использовать удаление del lst[i], обходя список в обратном порядке (так как удаление не влияет на элементы в начале списка): for i in reversed(range(len(lst))): if lst[i] == '0': del lst[i] # O(n) * k == O(n * k) В общем случае это квадратичный алгоритм O(n**2). Чем плохи квадратичные алгоритмы Квадратичные решения могут быть заметно медленнее для больших n, чем линейные. К примеру, линейный алгоритм для списка с миллионом элементов требует не больше чем C1 * 1000_000 шагов (инструкций), в то время как квадратичный алгоритм C2 * 1000_000_000_000, где C1, C2 константы, не зависящие от размера входного списка. C1, C2 примерно (по порядку величины) равны в этом случае, поэтому линейный алгоритм гораздо более предпочтителен, если k ~ n. Если миллион инструкций выполняются примерно за миллисекунду (даже моргнуть не успеете), то квадратичный алгоритм займёт целый день, если у кого-то терпения хватит ждать или батарейка не сядет пока закончится выполнение. Миллион элементов не является каким-то большим вводом в современных условиях (телефоны гигабайты памяти имеют). Как правило можно игнорировать константы (C1, C2 в примере) вне горячих точек (hot spots), к примеру, если константа на порядок изменится (в 10 раз), то миллион инструкций линейного алгоритма займёт в 10 раз дольше: ~10 миллисекунд (всё равно быстрее чем моргнуть успеете) и гораздо меньше многих часов для квадратичного алгоритма с ~1012 операций. Подытоживая: записывая алгоритм, стоит ориентироваться на простоту, читаемость и может ли он в принципе выполнить поставленную задачу. Микро-оптимизациями, которые уродуют код, улучшая только константу (C1, C2 в примере), лучше не заниматься, если profiler не говорит обратного. Если заранее не известно, что ввод ограничен по размеру, то стоит обратить внимание на порядок роста (big O) используемого алгоритма. В частности, если это заметно не затрудняет реализацию, то линейные алгоритмы (O(n)) гораздо более предпочтительны по сравнению с квадратичными (O(n*n)). Примеры из реального мира: https://accidentallyquadratic.tumblr.com/

    Ответ 2



    Различие состоит в количестве элементов в контейнерах и количестве нулей в каждом из них. Когда вы удаляете 0, то размер контейнера уменьшается. Например, для первого случая это можно представить следующим образом. Пусть идентификатор i является индексом элементов последовательности, а идентификатор n - общим количеством элементов в последовательности. После каждой итерации цикла индекс увеличивается на единицу, чтобы обратиться к следующему элементу. Итак, для первого цикла начальные значения i = 0, n = 10. Теперь пройдемся по итерациям цикла i = 0; remove( 0 ); n = 9 i = 1; remove( 0 ); n = 8 i = 2; remove( 0 ); n = 7 i = 3; remove( 0 ); n = 6 i = 4; remove( 0 ); n = 5 i = 5; n <= i итерация не выполняется. В результате имеем, что было выполнено 5 удалений. Это схематическое объяснение работы цикла. Реализация цикла может быть иной, но тем не менее данная модель демонстрирует, что используемый подход к удалению элементов из последовательности некорректен и ведет к непредсказуемому результату.

    Фиксированное количество знаков после запятой в Python

    #python

    
    Есть ли в python аналог функции toFixed() в JS? Мне нужно что-то вроде этого:
    
    >>> a = 12.3456789
    >>> a.toFixed(2)
    '12.35'
    >>> a.toFixed(0)
    '12'
    >>> b = 12.000001
    >>> b.toFixed(3)
    '12.000'
    
        
    


    Ответы

    Ответ 1



    Аналог Number.prototype.toFixed() из JavaScript в Python 3.6+: def toFixed(numObj, digits=0): return f"{numObj:.{digits}f}" Пример: >>> numObj = 12345.6789 >>> toFixed(numObj) '12346' >>> toFixed(numObj, 1) '12345.7' >>> toFixed(numObj, 6) '12345.678900' >>> toFixed(1.23e+20, 2) '123000000000000000000.00' >>> toFixed(1.23e-10, 2) '0.00' >>> toFixed(2.34, 1) '2.3' >>> toFixed(2.35, 1) '2.4' >>> toFixed(-2.34, 1) '-2.3'

    Ответ 2



    Прямого аналога нет. Можно попробовать a = float('{:.3f}'.format(x)) Пример: >>> x = 3.1234567 >>> x = float('{:.3f}'.format(x)) >>> x 3.123

    Ответ 3



    Вот так можно указать количество знаков после запятой при выводе: a = [1000, 2.4, 2.23456754323456, 2754.344] for i in a: print('%.3f' % i) # 3 знака после запятой Вывод: 1000.000 2.400 2.235 2754.344 Здесь подробнее.

    Ответ 4



    def toFixed(f: float, n=0): a, b = str(f).split('.') return '{}.{}{}'.format(a, b[:n], '0'*(n-len(b))) f = 7.123 print(toFixed(f, 10)) # 7.1230000000 print(toFixed(f, 2)) # 7.12

    Как сделать такие пятиугольники (+адаптивные) через css?

    #html #css #css3 #svg #адаптивная_верстка

    
    Думаю, что их стоит сделать svg polygon, но как это лучше реализовать, чтобы они
    и адаптивными были и подгонялись под ширину блока, в котором находятся?
    
    
        
    


    Ответы

    Ответ 1



    Решение SVG Решение адаптивно. Работает во всех браузерах. Вёрстка не сломается при изменении масштаба, так как все оформительские элементы: текст, патч, градиент находятся внутри SVG Если будет необходимость поменять начальные размеры блока, то нужно изменить проценты родительского контейнера .container .container { width: 30%; height: auto; box-shadow: 0 0 4px #131824; }
    Standard 24.0 Five User


    Ответ 2



    А чтобы была адаптивной, ее надо внедрить как фоновую картинку. Сохранить сей пример в отдельном файле name.svg background-Image: url(путь к файлу name.svg); background-size: cover; И второй вариант. Прописать прямо в css. background: url('data:image/svg+xml;utf8, '); background-size: cover;

    Ответ 3



    Решение CSS clip-path. Но надо учесть тот факт, что в IE && EDGE, работать не будет. .triangle { width: 250px; height: 140px; background: linear-gradient(45deg, #FFDD00, #FF00AE); -webkit-clip-path: polygon(0% 0%, 100% 0, 100% 60%, 50% 100%, 0 60%); clip-path: polygon(0% 0%, 100% 0, 100% 60%, 50% 100%, 0 60%); display: flex; text-align: center; justify-content: center; align-items: center; color: #fff; font-size: 40px; font-family: sans-serif; } .card { box-shadow: 0 0 40px rgba(0, 0, 0, 0.1); font-family: sans-serif; color: #aaa; border: 1px solid #ccc; display: inline-block; } .title { text-align: center; color: #333; font-size: 30px; padding: 10px; display: block; }
    Standard
    24.0
    • bla bla bla
    • bla bla bla
    • bla bla bla
    • bla bla bla
    • bla bla bla


    Поэлементное сложение списков различной длины

    #python #python_3x #списки

    
    Есть два списка: 
    
    a = [1,2,3]
    b = [4,5,6,7,8]
    
    
    Нужно получить такой результат:
    
    a + b = [5,7,9,7,8]
    
    
    Надеюсь, смысл понятен.
    Просто в голове одни костыли, хотелось бы найти более менее адекватное решение.
        
    


    Ответы

    Ответ 1



    Ещё несколько вариантов решения: longer = a if len(a) >= len(b) else b c = [x+y for x,y in zip(a,b)] + longer[min(len(a), len(b)):] или одной командой (менее читабельный вариант): c = [x+y for x,y in zip(a,b)] + (a if len(a) >= len(b) else b)[min(len(a), len(b)):] замеры времени выполнения для массивов длиной около 10^6: In [110]: print(len(a), len(b)) 1000000 1012345 In [104]: %timeit Sergey_Gornostaev(a, b) 267 ms ± 318 µs per loop (mean ± std. dev. of 7 runs, 1 loop each) In [105]: %timeit nick_gabpe(a, b) 200 ms ± 168 µs per loop (mean ± std. dev. of 7 runs, 1 loop each) In [106]: %timeit AtachiShadow1(a, b) 255 ms ± 558 µs per loop (mean ± std. dev. of 7 runs, 1 loop each) In [107]: %timeit AtachiShadow2(a, b) 239 ms ± 1.69 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) In [108]: %timeit AtachiShadow3(a, b) 200 ms ± 604 µs per loop (mean ± std. dev. of 7 runs, 1 loop each) In [109]: %timeit MaxU(a, b) 124 ms ± 1.26 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) setup: from random import randint a = [randint(0, 10**6) for _ in range(10**6)] b = [randint(0, 10**6) for _ in range(10**6+12345)] print(len(a), len(b)) # 1000000 1012345 def MaxU(a, b): return [x+y for x,y in zip(a,b)] + (a if len(a) >= len(b) else b)[min(len(a), len(b)):] def nick_gabpe(a, b): c=[] for x, y in zip(a,b): c+=[x+y] if len(a) > len(b): c+=a[len(a)-len(b)+1:] elif len(a) < len(b): c+=b[len(b)-len(a)+1:] return c def Sergey_Gornostaev(a, b): return [sum(i) for i in zip_longest(a, b, fillvalue=0)] def AtachiShadow1(a, b): c = [] la = len(a) lb = len(b) maxab = max(la, lb) minab = min(la, lb) for i in range(maxab): if i >= minab: if la < lb: c.append(0+b[i]) elif la > lb: c.append(a[i]+0) else: c.append(a[i]+b[i]) return c def AtachiShadow2(a, b): c = [] la = len(a) lb = len(b) maxab = max(la, lb) minab = min(la, lb) for i in range(maxab): try: c.append(a[i]+b[i]) except IndexError: if la < lb: c.append(0+b[i]) elif la > lb: c.append(a[i]+0) return c def AtachiShadow3(a, b): c=[] la = len(a) lb = len(b) for x, y in zip(a,b): c+=[x+y] if la > lb: c+=a[la-lb+1:] elif la < lb: c+=b[lb-la+1:] return c

    Ответ 2



    from itertools import zip_longest c = [sum(i) for i in zip_longest(a, b, fillvalue=0)]

    Ответ 3



    Спасибо огромное автору за достаточно клёвую задачку, мне (как новичку) было очень интересно разобраться как это работает) сообщение длинное, но надеюсь лёгкое в прочтении))): Предложенный в комментарии zip и в ответе zip_longest я решил оставить на последние варианты, а до них попробовать самостоятельно решить данный вопрос. И вот что я делал. Первый вариант был таким: a = [1, 2, 3] b = [4, 5, 6, 7, 8] c = [] for i in range(max(len(a), len(b))): if i >= min(len(a), len(b)): if len(a) == i + 1 and len(a) < len(b): c.append(0 + b[i]) else: c.append(a[i] + 0) else: c.append(a[i] + b[i]) print(c) Он, конечно же делает то, что должен. Но мне пришла вторая мысль о более логическом (как мне казалось) решении этого цикла. Второй вариант был таким: a = [1, 2, 3] b = [4, 5, 6, 7, 8] c = [] for i in range(max(len(a), len(b))): try: c.append(a[i] + b[i]) except IndexError: if i >= min(len(a), len(b)): if len(a) == i + 1 and len(a) < len(b): c.append(0 + bbb[i]) else: c.append(a[i] + 0) print(c) С одной стороны, мне казалось, что до тех пор, пока меньший список не перестанет итерироваться, будет выполняться тело try:. А когда меньший список закончится, возникнет except IndexError и исполнится тело ошибки. Так как и этот вариант тоже делает то, что задумано, логично было бы сравнить их по скорости выполнения. Я использовал timeit и получил следующие результаты: Вариант №1 - 8.045603216 на 1000000 (1млн) повторений Вариант №2 - 9.076056240 на 1000000 (1млн) повторений Я удивился. Я надеялся, что try: исключит лишнее выполнение if внутри цикла и тем самым ускорится. Но оказалось наоборот. После этого, я решил сравнить свои варианты с вариантом Sergey Gornostaev, и timeit второй раз указал на неэффективность моих методов: Вариант №1 - 8.045603216 на 1000000 (1млн) повторений Вариант №2 - 9.076056240 на 1000000 (1млн) повторений Sergey Gornostaev - 6.960991073 на 1000000 (1млн) повторений Идея того, что на стэковерфлоу чаще всего предлагают "опытные" ответы в очередной раз подтвердилась)))) 1 секунда выигрыша у Sergey Gornostaev)) Но я подумал, стандартная библиотека == оптимизированный код. Я пошёл оптимизить свой код - в моих вариантах функции len(), max(), min() запускаются в каждой итерации цикла, а зачем мне 5 раз len(a) просить?)))) я тоже подумал что это немного тупо и надо исправить)))) вынес их в переменные до цикла и подправил логику if. Вариант №1.1: a = [1, 2, 3] b = [4, 5, 6, 7, 8] c = [] la = len(a) lb = len(b) maxab = max(la, lb) minab = min(la, lb) for i in range(maxab): if i >= minab: if la < lb: c.append(0+b[i]) elif la > lb: c.append(a[i]+0) else: c.append(a[i]+b[i]) print(c) Вариант №2.1: a = [1, 2, 3] b = [4, 5, 6, 7, 8] c = [] la = len(a) lb = len(b) maxab = max(la, lb) minab = min(la, lb) for i in range(maxab): try: c.append(a[i]+b[i]) except IndexError: if la < lb: c.append(0+b[i]) elif la > lb: c.append(a[i]+0) print(c) И да, оптимизация сработала: Вариант №1.1 - 4.774997384 на 1000000 (1млн) повторений Вариант №2.1 - 5.907061396 на 1000000 (1млн) повторений Sergey Gornostaev - 6.960991073 на 1000000 (1млн) повторений Почти двукратный прирост к скорости, за счёт правильного написания кода. И оба варианта быстрее предложенной библиотеки))) И когда я уже было хотел внести очередную правку в свой ответ, появился ответ автора: a = [1,2,3] b = [4,5,6,7,8] c=[] for x, y in zip(a,b): c+=[x+y] if len(a) > len(b): c+=a[len(a)-len(b)+1:] elif len(a) < len(b): c+=b[len(b)-len(a)+1:] print(c) И что же timeit? Разнёс в щепки, все предыдущие варианты))): Вариант №1.1 - 4.774997384 на 1000000 (1млн) повторений Вариант №2.1 - 5.907061396 на 1000000 (1млн) повторений Sergey Gornostaev - 6.960991073 на 1000000 (1млн) повторений Автор - 3.151485595 на 1000000 (1млн) повторений Выигрыш 1,5 секунды перед моим "быстым" оптимизированным вариантом. Идея хорошего ответа на СО второй раз за один вопрос подтвердила себя)))))) НО! что ещё более круто в ответе самого автора, это использование zip. В ответе Sergey Gornostaev и в моих вариантах используется концепция большего списка, то есть, for будет делать столько циклов сколько элементов в большем списке - это есть ПЛОХО. Наводящий вопрос - что будет, если один из списков будет пустым? А вот что: a = [] Вариант №1.1 - 4.960243867 на 1000000 (1млн) повторений Вариант №2.1 - 7.668313717 на 1000000 (1млн) повторений Sergey Gornostaev - 6.865756772 на 1000000 (1млн) повторений Автор - 1.848900008 на 1000000 (1млн) повторений Вот это поворот!!! Вариант №1.1 остался таким же (0.2 на погрешность). А вот Вариант №2.1 (try except) просто провалился - из-за того что a = [], каждая итерация for теперь приводит к except, что и увеличило время выполнения. Вариант Sergey Gornostaev тоже,как и 1.1 не изменился во времени исполнения (0.1 на погрешность). Но вот ответ автора показал себя в полной красе, это по круче любой "чашки сахара" (из мультика про "вот это поворот"))))) почти 3-х кратное превосходство на самым быстрым вариантом "длинного списка"! Но это ещё не всё!))) Я же помнил стандартная библиотека == оптимизированный код, а код автора немножко не оптимизирован)))) функции len(a) и len(b) вызываются дважды за выполнение. Значит их можно посчитать один раз в начале и потом пользоваться переменной)): a = [1,2,3] b = [4,5,6,7,8] c=[] la = len(a) lb = len(b) for x, y in zip(a,b): c+=[x+y] if la > lb: c+=a[la-lb+1:] elif la < lb: c+=b[lb-la+1:] И вот что говорит timeit: a = [1,2,3]: не оптимизированный код автора - 3.138068215 оптимизированный код автора - 2.908475165 a = []: не оптимизированный код автора - 1.909198691 оптимизированный код автора - 1.642370166 Выигрыш на уровне 0.25 секунды у оптимизированного кода. И это уже точное 3-х кратное превосходство над кодом "длинного списка"! Это круто)))) P.S. 1. Все измерения проводились на одном компьютере, и в приблизительно одинаковых условиях (отличия мог вносить только открытый рядом Chrome), из этого следует что отношение времени в выполнении разных логик будут другими на другом компьютере, а здесь показывается лишь приблизительная ОТНОСИТЕЛЬНАЯ скорость выполнения логик. 2. Я не профессионал, даже не любитель, timeit я гуглил во время написания ответа. Пока что ко мне больше применимо понятие "Script kiddie", но я учусь))))) Именно поэтому, я предполагаю, что мои исследования в этом вопрос-ответе будут содержать ошибки и не точности. И буду рад если о них мне расскажут более опытные программисты)))). 3. Ещё раз БОЛЬШОЕ спасибо автору вопроса-задачи и тем кто отвечал и комментировал его, мне было приятно несколько раз удивляться своей несостоятельности, и так же было приятно учиться на этом)) 4. Приведённые измерения и отличия на 1 млн повторений могут вызвать закономерный вопрос о том, а стоит ли париться из-за таких мелких отличий, тем более что речь идёт о Python а не о C++ к примеру. И я считаю что каждый сам решит стоит ли оно того))))))) Как минимум для разминки это можно было сделать)

    Ответ 4



    Ну и напишем свой велосипед: a = [1,2,3] b = [4,5,6,7,8] c=[] for x, y in zip(a,b): c+=[x+y] if len(a) > len(b): c+=a[len(a)-len(b)+1:] elif len(a) < len(b): c+=b[len(b)-len(a)+1:] print(c) # [5, 7, 9, 6, 7, 8]