Страницы

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

четверг, 13 февраля 2020 г.

Можно ли в Python создать экземпляр класса имея только его переменную?

#python #python_3x


Допустим есть переменная типа str

a = 'test'


можно ли допустим создать экземпляр класса при помощи значения "тест"
Что я имею ввиду:

'test'.название_класса

    


Ответы

Ответ 1



Можно используя __class__. class A(): pass obj = A() new_obj = obj.__class__()

Как сделать сортировку названий как в проводнике Windows?

#python #python_3x #сортировка


Есть список файлов и если на Python сделать sort(), то список получаеться не такой
же как в проводнике Windows (сортировка по имени). 

Как сделать сортировку по имени такой же как и в Windows Проводнике?
    


Ответы

Ответ 1



воспользуйтесь модулем natsort: In [45]: from natsort import natsorted # pip install natsort In [46]: files = ["7.png", "10.png", "5.png"] In [47]: sorted(files) # Vanilla Python sorting Out[47]: ['10.png', '5.png', '7.png'] In [48]: natsorted(files) # natsort sorting Out[48]: ['5.png', '7.png', '10.png']

Проверить, что в строке число

#python


Пользователь вводит значения через запятую. Предполагается что он ввел числа. Допустимым
являются как int, так и float.
Как проверить ввел ли пользователь числа или нет ?
Я пробовала из введенной строки удалить все пробелы, точки и запятые, а затем проверить
.isdigit(). Но мне показалось это решение слишком громоздким.

user_num_str = input('Enter numbers separated by commas: ')
user_num_str_check = user_num_str.replace(' ', '')
user_num_str_check1 = user_num_str_check.replace(',', '')
user_num_str_check2 = user_num_str_check1.replace('.', '')
if not user_num_str_check2.isdigit():
    print('Seams like string!')


Буду очень признательна, если посоветуете более простой метод.
    


Ответы

Ответ 1



Задачу можно разделить на 2 части: 1. Разбить введенные пользователем данные на элементы(через запятую) 2. Проверить, является ли введенный элемент числом Сначала определим функцию проверки на число: def is_number(s): try: float(s) return True except ValueError: return False Допустим пользователь ввел строку: s = "0 1.2.3, 11, 22, 33, 56.52, .225, 1.000000e+50, 1e50, NAN" Тогда ее можно будет разбить на отдельные элементы: lst = s.split(',') И проверить, является ли каждый элемент числом или нет: for element in lst: print(element, end='') if is_number(element): print(" - число") else: print(" - не число") Вывод: 01.2.3 - не число 11 - число 22 - число 33 - число 56.52 - число .225 - число 1.000000e+50 - число 1e50 - число NAN - число Обратите внимание, что такой подход признает NAN числом, так как float('NAN') обработается без ошибки. То же самое с True и False. Надо ли проверку на NAN, True, False - это отдельный вопрос. Во всяком случае текущая функция проверит, что с введенными данными вы дальше сможете работать как с числами. PS Использовать try except с приведением строки к числу возможно возможно не самый лучший вариант. Однако я не знаю другого хорошего простого варианта проверять числа 1e50 или .125. Есть несколько альтернативных вариантов: 1. Использовать регулярки, но как мне кажется они сложнее для понимания. И регулярку, которая будет одновременно воспринимать и научные способы записи вида 1e50 и записи .5552 будет выглядеть довольно сложно. Как говорится, у нас была проблема. Мы решили ее регуляркой, теперь у нас 2 проблемы 2. Использовать str.isnumeric() или str.isdigit() Тогда у всех элементов в листе надо удалить лишние пробелы lst = [e.replace(' ', '') for e in lst] И снова проверить: for element in lst: print(element, end='') if element.isdigit(): print(" - число") else: print(" - не число") Вывод: 01.2.3 - не число 11 - число 22 - число 33 - число 56.52 - не число .225 - не число 1.000000e+50 - не число 1e50 - не число NAN - не число Однако, этот способ проверяет только, что строка состоит из чисел. По этому числа с плавающей точкой или с e не будут признаны числами. Так же это не сработает для отрицательных чисел.

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

#java #строки #подстрока


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

Итак, есть String sentence;. Надо удалить подстроку из слова, начинающуюся и заканчивающуюся
заданными символами, например, "а" и "б". Удалить только в слове с максимальной длиной
подстроки. 

Сам я разбил предложение на слова в цикле, искал слова, которые содержат "а" и "б"
и выбирал из них самое длинное, где и удалял подстроку. Однако, слово может быть длиннее,
а подстрока короче. 

Как это сделать лучше? 

Пример: есть предложение а+б_а++б_+а+++б+_++а++++б++, где + любой символ, а _ это
пробел. В нашем случае должна удалиться подстрока от а до б в последнем слове (т.к.
она самая длинная) и останется такое предложение: а+б_а++б_+а+++б+_++аб++.
    


Ответы

Ответ 1



Для простоты задачи предположним, что слова разделены только пробельными символами (имеются ввиду любые пробелы в Unicode). import java.util.regex.Pattern; import java.util.regex.Matcher; public class HelloWorld { public static void main(String[] args) { String text = "а+б а++б +а+++б+ ++а++++б++"; // паттерн означает строку, которая содержит один или более непробельных символов "\\S+" // перед которыми подстрока "а" (франгмент (?<=а) — это так называемый positive lookbehind), // после которых подстрока "б" (франгмент (?=б) — это так называемый positive lookahead). String regexPattern = "(?<=а)\\S+(?=б)"; // получаем объект для итерации по всем совпадениям Matcher matcher = Pattern.compile(regexPattern).matcher(text); // для хранения максимульной длины совпадения int maxLength = 0; // для хранения индексов самого длинного совпадения int startIndex = -1; int endIndex = -1; // итерируемся по всем совпадениям while (matcher.find()) { int length = matcher.end() - matcher.start(); // если совпадение самое длинное, то сохраняем его индексы if (length > maxLength) { startIndex = matcher.start(); endIndex = matcher.end(); } } // если совпадение найдено (оно будет самым длинным), то вырезаем его if (startIndex > 0) text = text.substring(0, startIndex) + text.substring(endIndex); System.out.println(text); } }

Ответ 2



Если я верно понял задачу, то надо найти максимальную подстроку в слове (слова разделены пробелами), которая начинается на 'а', заканчивается на 'б', причем внутри этой подстроки нет ни а, ни б и удалить все символы между началои подстроки и концом. Если так, то это можно за линейное время сварганить string RemoveSubString(string str, char start, char end) { int s = -1; int e = -1; int pointer = 0; while(pointer < str.Length) { while(pointer < str.Length && str[pointer]!=start && str[pointer]!=' ') pointer++; if (pointer < str.Length && str[pointer]==start) { int s1 = pointer; pointer++; while(pointer < str.Length && str[pointer]!=end && str[pointer]!=' ') pointer++; if (pointer < str.Length && str[pointer] == end) { int e1 = pointer; if(s == -1 || (e-s) < (e1-s1)) { s=s1; e=e1; } } else pointer++; } else pointer++; } if ((e-s) < 2) return str; return str.Substring(0, s+1) + str.Substring(e, str.Length-e); } Проверка Console.WriteLine(RemoveSubString("а+б а++б +а+++б+ ++а++++б++", 'а', 'б')); Console.WriteLine(RemoveSubString("а+б_а++б_+а+++б+_++а++++б++", 'а', 'б')); Console.WriteLine(RemoveSubString("1-----2-------2--------2", '1', '2')); Console.WriteLine(RemoveSubString("12", '1', '2')); Console.WriteLine(RemoveSubString("21", '1', '2')); Console.WriteLine(RemoveSubString("2-1-2", '1', '2')); Console.WriteLine(RemoveSubString("1-2", '1', '2')); Console.WriteLine(RemoveSubString("1222222", '1', '2')); Console.WriteLine(RemoveSubString("2111111", '1', '2')); Console.WriteLine(RemoveSubString("1-111111", '1', '1')); Console.WriteLine(RemoveSubString("1-11111--1", '1', '1')); Вывод а+б а++б +а+++б+ ++аб++ а+б_а++б_+а+++б+_++аб++ 12-------2--------2 12 21 2-12 12 1222222 2111111 1111111 1-111111

C++. Предварительное объявление членов классов за их пределами

#cpp #классы #объявление


У меня сложилась такая ситуация, что есть два класса, каждый из которых нуждается
в конструкторе другого. Для этого нужно, чтобы они видели не только объявления (прототипы),
но и определения друг друга одновременно, что невозможно. Значит, каждый класс должен
видеть сверху по крайней мере прототип конструктора другого.

Вот мой код:

#include 

class Euros;
Euros::Euros(double euros = 0);

class Dollars
{
    private:
        double m_dollars;

    public:
        Dollars(double dollars = 0) : m_dollars(dollars)
        {
        }

        operator double() const { return m_dollars; }
        operator Euros() const { return Euros(m_dollars * 0.89); }

        double getDollars() const { return m_dollars; }
        void setDollars(double dollars) { m_dollars = dollars; }
};

class Euros
{
    private:
        double m_euros;
    public:
        Euros(double euros) : m_euros(euros)
        {
        }

        operator double() const { return m_euros; }
        operator Dollars() const { return Dollars(m_euros * 1.12); }

        double getEuros() const { return m_euros; }
        void setEuros(double euros) { m_euros = euros; }
};


Здесь для каждого класса перегружается операция преобразования типов друг в друга,
для чего требуется возвращать вновь созданный с помощью конструктора экземпляр противоположного
класса. С классом Euros всё нормально, т.к. он видит полное определение класса Dollars,
а значит видит и конструктор. С классом Dollars всё наоборот: он вообще не видит Euros.
В 3 строке я объявил прототип Euros, но этого недостаточно, т.к. для создания объекта
нужен ещё и конструктор. 

Я знаю, что методы класса достаточно только объявить внутри него, а определение может
быть уже после за его пределами. Но я не знаю, можно ли сделать наоборот: определить
внутри класса, а объявить перед ним. В 4 строке я попытался это сделать, но получил
ошибку "invalid use of incomlete type 'class Euros'". Естественно, были и другие ошибки,
вытекающие из этой, но данная ошибка источник всех проблем.

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


Ответы

Ответ 1



Простое вынесите реализации "перекрёстных" методов (одного из них) наружу из определения класса и поместите ниже - после определения второго класса class Euros; class Dollars { ... operator Euros() const; ... }; class Euros { ... operator Dollars() const { return Dollars(m_euros * 1.12); } ... }; inline Dollars::operator Euros() const { return Euros(m_dollars * 0.89); } Вы и сами написали об этом в вопросе: "Я знаю, что методы класса достаточно только объявить внутри него, а определение может быть уже после за его пределами." Только применять это знание вам надо было обычным способом к вашим операторам преобразования, а не каким-то "вывернутым" образом к конструкторам.

Избавиться от Unnecessary boxing

#java #intellij_idea


Есть такой код

int i = 5;
Double d = Double.valueOf(i);


(на самом деле код такой

int getInt() {
  ....
}

Double d = Double.valueOf(getInt());


но не суть)

На строку

Double d = Double.valueOf(i);


IDEA пишет


  Warning: Unnecessary boxing. 


Но какой же он Unnecessary, если мне нужно примитив int привести к объекту Double?

На строку

Double d = i


я уже получаю ошибку


  Incompatible types. Required: java.lang.Double Found: int


Это баг анализатора, или все-таки как-то можно присвоение переписать?
    


Ответы

Ответ 1



Примитивный тип int нужно сначала привести к примитивному типу double - после этого boxing уже не нужен Double d = (double) i;

Ответ 2



У меня IDEA пишет также. Если возможен то используйте такой вариант Integer i = 5; Double d = getInt().doubleValue(); Либо, используйте, как IDEA и предлагает Double d = (double) getInt();

Потерял текущую ветку с кодом - как восстановить?

#android_studio #git #git_commit #git_push


У меня случился полный пиндец... Целую неделю писал код в Android Studio в базовой
ветке master. Изменения коммитил, но не пушил на сервер.

В итоге, когда собрался запушить на сервер, решил сначала сохранить то что было на
сервере в ветке master в отдельную ветку. Используя инструменты AS, в нижнем правом
углу, выбрал ветку master на сервере, нажал checkOutAs, ввел новое имя "develop/test1"
и нажал enter. После чего проект просто обнулился до состояния сервера, в папке проекта
так же все файлы удалились, и пропала панель Version Control.

Вот последние сообщения в логах:


  12:29 5 files committed: Отказался от использования элементов экшен бара
  
  13:29 1 file committed: Схема базы данных
  
  13:30 Checked out new branch develop/test1 from origin/master (show balloon)


Помогите понять что произошло. И самое главное - как восстановить потерянный код?!
Где-то же дожна была сохраниться история коммитов???
    


Ответы

Ответ 1



У вас все коммиты должны остаться в локальном репозитории. Попробуйте выполнить git reflog, чтобы отобразить список всех сделанных вами коммитов. Если найдете там нужный (последний ваш коммит), то сделайте git checkout 1c7474c, где "1c7474c" - это id нужного коммита.

Ответ 2



Еще один более простой и правильный способ решения проблемы. По каким то непонятным причинам в Android Studio иногда слетает Git, что приводит к вышеописанным проблемам. И на самом деле, ничего переключать и восстанавливать не нужно. Достаточно зайти в меню VSC и нажать Enable version control integration, после чего в появившемся окошке выбрать нужный вариант (в моем случае Git).

Смена контента каждые 5 секунд Laravel + Vue + AJAX

#ajax #laravel #vuejs #laravel_56 #laravel_57


Как сделать, чтобы баннер менялся на следующий каждые 5 секунд?

Компонент






Контроллер

public function list()
{
  $banner = Banner::where('published', 1)->first();

  return response()->json($banner);
}

    


Ответы

Ответ 1



Не нужно слать запросы для получения только одной сущности из БД. Ниже пример постраничной зацикленной подгрузки контента: сама страница не перезагружается в браузере, а происходит лишь подгрузка содержимого в компонент Vue через AJAX с параметром page. При этом номер текущей "партии" содержимого page сохраняется в localStorage. Применительно не только к баннерам: это может быть виджет новостей, ротатор изображений и др. Маршрутизатор // BannerController замените на свой. Route::get('/banners/list', 'BannerController@list'); Контроллер public function list(Request $request) { // Обрабатываем запросы только по AJAX. if ($request->ajax()) { $banners = Banner::where('published', 1)->paginate(5); return response()->json($banners, 200); } // Запретим прямой доступ на страницу. abort(403, 'Unauthorized action.'); } Примерное содержимое компонента: