Страницы

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

среда, 11 декабря 2019 г.

Частота слов в тексте

#python #php #bash #perl


Ниже приведенный скрипт на Python подсчитывает частоту слов в тексте (непрерывных
последовательностей букв за исключением знаков препинания) и выводит таблицу результатов. 

Работает правильно. Вопрос вот в чем: можно ли сделать то же самое проще (например,
меньше строк кода) на Python, Bash, PHP, Perl или это лучший способ?

import sys
import string

file = open(sys.argv[1], "r")
text = file.read()
file.close()

table = string.maketrans("", "")
words = text.lower().split(None)

frequencies = {}
for word in words:
    trimmed = word.translate(table, string.punctuation)
    frequencies[trimmed] = frequencies.get(trimmed, 0) + 1

keys = sorted(frequencies.keys())
for word in keys:
    print "%-32s %d" % (word, frequencies[word])

    


Ответы

Ответ 1



В вашем примере встречая подобную строку: "aa,bb,cc" она считается как "aabbcc 1", а должно быть: aa 1 bb 1 cc 1 Итак, мой вариант на Perl: #!/usr/bin/perl use strict; my %result; while (<>) { $result{ lc $_ }++ for /(\w+)/g; } printf "%-32s %d\n", $_, $result{$_} for sort keys %result; можно его конечно скомпоновать и в одну строчку. но будет нечитаемо.

Ответ 2



python, регекспы import re import sys import operator file = open(sys.argv[1], "r") text = file.read().decode("utf8") file.close() words = re.findall(r"(\w+)", text, re.UNICODE) stats = {} for word in words: stats[word] = stats.get(word, 0) + 1 stats_list = sorted(stats.iteritems(), key = operator.itemgetter(1)) for word, count in stats_list: print "%-32s %d" % (word, count)

Ответ 3



Мой вариант: #!/usr/bin/perl use strict; my %frec; sub calc{ $frec{ $1 }++ while( $_[0] =~ /\b(\S+)\b/g ); } my $fileName = shift or die( "Uasge: $0 filenameWithText" ); open FF, $fileName; calc( $_ ) for( ); foreach( sort{ $frec{$b} <=> $frec{$a} } keys %frec ){ printf( "%-32s %d\n", $_, $frec{ $_ } ); } close FF;

Ответ 4



Скрипт на bash/awk, для коллекции: #/bin/bash if [ -z "$1" ] then echo "Usage: `basename $0` filename" exit 1 fi for x in $(sed -rn 's/\W+/ /gp' $1); do echo $x done | awk '{print tolower($0)}' | sort | awk ' { if (!word) { word = $1 num = 0 } else if (word == $1) { num++ } else { print word, num+1 word = $1 num = 0 } }'

Ответ 5



Мой скромный вариант: import sys, string text = sorted(open(sys.argv[1], 'r').read().translate(string.maketrans('', ''), string.punctuation).split()) for i in range(len(text) - 1): if text[i + 1] == text[i]: continue print '%s %d' % (text[i], text.count(text[i])) для python3: import sys, string text = sorted(open(sys.argv[1]).read().lower().translate(''.maketrans('', '', string.punctuation)).split()) for i in range(len(text) - 1): if text[i + 1] == text[i]: continue print('{0:>20} {1:<}'.format((text[i]), text.count(text[i])))

Ответ 6



Подсчёт частоты слов с поддержкой Unicode (.casefold(), \w+): текст, в кодировке из локали, задаётся из файлов, указанных в командной строке, или со стандартного ввода (если не указаны) слова выводятся в порядке убывания популярности кодировка для вывода может отличаться от кодировки на входе выводит построчно, с указанным в вопросе форматированием (ширина под слово — 32 символа) #!/usr/bin/env python3 import fileinput import re from collections import Counter words = (word for line in fileinput.input() for word in re.findall(r'\w+', line.casefold())) for word, count in Counter(words).most_common(): print("%-32s %d" % (word, count)) Вот версия, близкая к поведению Питон 2 кода из вопроса: читает байты из файла, переводит их в нижний регистр, разбивает на слова по стандартному пробелу (не поддерживает Unicode) удаляет ascii пунктуацию из каждого слова (может пустая строка остаться) считает получившиеся слова, сортирует их по величине байт выводит построчно, с указанным в вопросе форматированием (ширина под слово — 32 байта) #!/usr/bin/env python3 import os import string import sys from collections import Counter from pathlib import Path words = Path(sys.argv[1]).read_bytes().lower().split() chars_to_trim = string.punctuation.encode() trimmed = (word.translate(None, chars_to_trim) for word in words) for word, count in sorted(Counter(trimmed).items()): sys.stdout.buffer.write(b"%-32s %d%s" % (word, count, os.linesep.encode())) Два примера разный вывод генерируют как правило.

Ответ 7



Можно воспользоваться модулем nltk, который предназначен для работы с естественными текстами: In [54]: from nltk import word_tokenize, FreqDist In [55]: data = open(r'c:/temp/TWAIN.LOG').read() In [56]: fdist = FreqDist(word.lower() for word in word_tokenize(data) if word.isalpha()) 10 наиболее часто встречающихся слов: In [57]: fdist.most_common(10) Out[57]: [('message', 10), ('ctwtrace', 4), ('ctwunk', 3), ('dsm', 3), ('dsmentrydiagexit', 3), ('rc', 3), ('cc', 3), ('thunker', 2), ('scannerredirection', 2), ('to', 2)] весь словарь целиком: In [58]: dict(fdist) Out[58]: {'message': 10, 'ctwunk': 3, 'reset': 1, 'log': 1, 'starting': 1, 'thunker': 2, 'why': 1, 'ca': 1, 'we': 1, 'find': 1, 'the': 1, 'window': 1, 'dsm': 3, 'dsmentrydiagexit': 3, 'rc': 3, 'cc': 3, 'ctwtrace': 4, 'scannerredirection': 2, 'to': 2, 'null': 2, 'control': 2, 'identity': 2, 'getfirst': 1, 'getnext': 1}

Ответ 8



Php вариант частоты вхождений слов в тексте: $text = preg_replace("/[\s\.\,\!]+/", " ", $text); $text = explode(" ", $text); foreach (array_count_values($text) as $key => $value) { echo '
'.$key.'-->'.$value; }

Что такое token?

#терминология


Часто в программирование встречаю это название или фразу на подобии "получаю токен"
Что оно обозначает?    


Ответы

Ответ 1



Термин token имеет много разных смыслов. Один из смыслов разъяснен в посте @Heidel, но это лишь один из смыслов, причем не самый частый. В контексте вопроса скорее всего речь идет о немного другом смысле. Под токеном понимается замещение объекта неким обозначением/идентификатором (часто просто целым числом или строкой). Например: идентификатор сессии это классический токен. Токены широко применяются обычно в системах авторизации/идентификации и проч. Технически обычно реализуются в виде записи в БД, где токен является идентификатором записи о данных юзера или предоставленного доступа. Обычно в этом случае токен вычисляется как хэш комбинации данных юзера (логина), времени создания и ключей сервера ну и проч. Смысл всей этой байды в том, что вместо того, чтобы передавать юзеру целый сонм разных данных достаточно дать ему в руки токен и сказать: вот тебе токен и с помощью него можно при необходимости сделать все что надо. Это и удобно и меньше рисков засветки данных.

Ответ 2



Токен - это нечто, чем должен обладать пользователь, чтобы получить доступ к ресурсу. Например, доступ к серверу можно организовать через файл Token.dat для каждого пользователя. Каждому пользователю нужно выдать его персональный файл Token.dat, в котором содержится полный список необходимых данных для доступа к ресурсу, например адрес и порт сервера, идентификатор пользователя и его ключ.

Ответ 3



Лексема (token) - минимальная единица языка, имеющая самостоятельный смысл. Существуют следующие виды лексем имена (идентификаторы); ключевые слова; знаки операций; разделители; литералы (константы).

Книга о том как писать компиляторы на языке C/C++ [закрыт]

#cpp #c #книги


        
             
                
                    
                        
                            Closed. This question is off-topic. It is not currently
accepting answers.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Want to improve this question? Update the question so
it's on-topic for Stack Overflow на русском.
                        
                        Closed 4 года назад.
                                                                                
           
                
        
Здравствуйте. Подскажите, пожалуйста, хорошую книгу, на русском языке о том, как
написать компилятор на языках С/С++. И ещё книгу или хорошую статью 
"как писать парсеры математических выражений".
Заранее спасибо.    


Ответы

Ответ 1



Для написания парсеров на C умудрённые опытом домохозяйки используют lex/yacc. По нему много литературы, например, O'Reilly. Для написания полновесного компилятора читайте Dragon Books. Не жалуйтесь, что книги сложные.

Ответ 2



Перед чтением книг в стиле "книга дракона", я бы рекомендовал просмотреть очень занимательное введение в разработку компиляторов - Джек Креншоу. Давайте создадим компилятор!. Хотя там используют старый диалект паскаля, но от этого книга не стает хуже. Но вот базисные вещи научит писать. После ее прочтения и анализа простенький скриптовый язык или компилятор (хотя я бы назвал транслятором то, что получиться, так как скорее всего научитесь писать программу, которая переведет код с Вашего языка в С или ассемблер) будет уже не так сложно.

Ответ 3



Если вести речь вообще о внутреннем устройстве и разработке языков, то Языки программирования: разработка и реализация Т. Пратт, М. Зелковиц безусловно стоит почитать. Я читал когда-то первое издание, а вот современное (4-е) с кучей новых языков, к сожалению, как-то в продаже не попадается. Update Вот чуть погуглил и с 3-ей примерно страницы качнул его (4-е на русском, правда, djvu (в транспорте на моих девайсах не почитаешь...)).

Ответ 4



Вот ещё неплохая книга: Языки программирования и методы трансляции

Ответ 5



Книга Дракона

Singleton и реализация

#cpp


Если я создаю класс в качестве одиночки, то нужно ли реализовать оперетор присваивания,
конструктор копирования, операторы сравнения классов и т.д? Как их вообще записать?
Просто без объявить, но не писать реализацию?
И заодно спрошу, как реализовать Singleton, если объект класса будет создаваться как
Class * c = new Class();

а не так 
Class c;
    


Ответы

Ответ 1



Классический (и наиболее изящный) метод объявления синглтона на C++ — синглтон Майерса. Пример: class Singleton { public: static Singleton& Instance() { // согласно стандарту, этот код ленивый и потокобезопасный static Singleton s; return s; } private: Singleton() { ... } // конструктор недоступен ~Singleton() { ... } // и деструктор // необходимо также запретить копирование Singleton(Singleton const&); // реализация не нужна Singleton& operator= (Singleton const&); // и тут }; Начиная с C++11, правильнее писать так: Singleton(Singleton const&) = delete; Singleton& operator= (Singleton const&) = delete; Теперь по пунктам: Оператор присваивания не нужен. Поскольку он во многих случаях создаётся компилятором «за вашей спиной», нужно задекларировать его приватным, чтобы им никто не мог воспользоваться. В C++11 вы можете прямо убрать его при помощи конструкции «= delete». То же для конструктора копирования. В операторах сравнения нет нужды, так как всё равно есть лишь один экземпляр. Поскольку автоматически операторы сравнения не создаются, вам не нужно ни о чём беспокоиться. Использовать синглтон, создавая его явно, нельзя: ведь если вы смогли объявить один экземпляр, то сможете объявить сколько угодно! Поэтому варианты «ручного» создания мы исключили, сделав конструктор приватным. Получить ссылку на синглтон для работы с ним можно только так: Singleton& instance = Singleton::Instance();

Как удалить все пробелы из строки в Python?

#python #функции


Нагуглил функцию strip(), но она удаляет только первый и последний пробел, а мне
нужно все. 
Например, если a = ' sd dfsdf  dfsfs', то нужно получить a = 'sddfsdfdfsfs'. 
Есть ли такая функция или надо через цикл как-то делать?    


Ответы

Ответ 1



a.replace(' ', '')

Ответ 2



strip() может удалить не только пробел, но и табы и другие символы, которые считаются пробелом, включая Юникодные пробелы, если strip() вызван для Юникодной строки: >>> import string >>> string.whitespace '\t\n\x0b\x0c\r ' >>> string.whitespace.strip() '' >>> import sys >>> s = ''.join(unichr(i) for i in xrange(sys.maxunicode) if unichr(i).isspace()) >>> s[:15] u'\t\n\x0b\x0c\r\x1c\x1d\x1e\x1f \x85\xa0\u1680\u180e\u2000' >>> s.strip() u'' Поэтому аналог strip(), который удаляет пробел во всей строке: s = ''.join(s.split()). Или, тоже самое, используя регулярные выражения: s = re.sub(r'\s+', '', s, flags=re.UNICODE). Или, в коде, где важна производительность, bytes.translate() может быть использован, чтобы удалить все стандартные (string.whitespace в С локале) пробелы из ascii строки: >>> b'a\tb\nc'.translate(None, b'\t\n\v\f\r ') 'abc'

Ответ 3



Если неизвестно количество пробелов, и табов, самый простой способ: a = 'Some string with meny space or tabs' b = a.split() b = ''.join(b) b >>> Somestringwithmenyspaceortabs

Конвертация большого CSV в XLS

#php #excel #csv


В кастомной CMS есть возможность скачать рабочие данные в формате Excel. Сейчас это
происходит через вызов внешнего конвертера CSV → XLS. Никакого стилевого оформления
данных нет и не требуется, это просто аналог csv в более понятном для клиентов виде.
Хочется заменить внешний конвертер на что-нибудь родное для PHP.  

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


Ответы

Ответ 1



Я бы не стал писать отдельный ответ, но вы отметили что оформление вас не интересует. Чтож, мне кажется вам надо разбить задачу на 2 части: 1) Генерация данных по кусочкам - каждый кусок должен быть такого размера, чтобы ваш PHP (с вашими ограничениями по памяти, ресурсам процессора и прочим настройкам) мог спокойно обработать его. 2) Собственно запись данных из конкретного кусочка всей информации в файл. Исходя из такого подхода, вы можете запустить некий цикл/очередь, и по очереди обработать любое нужное вам количество информации (!). А затем собственно сконвертировать в формат Excel. Вы конечно же можете использовать вышеозвученный CSV формат, а затем конвертировать его в Excel. Однако, я могу предложить лучшую альтернативу - формат XML (XML Spreadsheet 2003) или Open XML. Для использования этого формата вовсе не обязательно использовать ту же библиотеку PHPExcel, вы можете написать и собственный код, так как вас не интересует оформление, и поэтому большая часть функций PHPExcel вам вообще не нужна. Что вам нужно это вручную создать нужную структуру формата файла в XML, и в цикле выдавать в него значения из кусочков (file append). В итоге, после завершения обработки всех данных вы получите файл в формате .XLSX и ваш клиент спокойно сможет открыть его в Excel. В результате у вас получится что-то вроде этого: Author Author 2015-04-19T21:57:54Z 14.00 9264 20100 0 24 False False Column 1 Column 2 Row 1 Row 2
Собственно, если вы решите пойти таким путём - вы можете поискать в Гугле по запросам "OpenXML generate Excel" и посмотреть как это делается в разных языках (не только через PHP). Учитывая отсутствие оформления - большая часть проблем у вас будет не с генерацией контента, или конвертированием в XML, а в том чтобы создать исходный шаблон и добиться того, чтобы Excel открывал его правильно.

Ответ 2



Не совсем техническое решение, но из личного опыта - уберите конвертер и отдавайте клиентам файл с расширением CSV по кнопке "Экспорт в Excel". Excel выставляет ассоциации с CSV по умолчанию. У файлов показывается экселевский значок - вобщем, для окончательного пользователя файл ничем не отличим от XLS. Особенно если отображение расширений отключено (опять же, по умолчанию).

Ответ 3



Читать потоково. Писать потоково: PHP_XLSXWriter P.S. Но вообще я бы прислушался к совету @PashaPash и не городил велосипед. CSV прекрасно открывается Экселем.

Как перевести дату из формата yyyy-mm-dd в общепринятый вид?

#java


Есть дата вида "2015-05-15". Как из неё сделать дату вида "15 мая 2015"?
    


Ответы

Ответ 1



С помощью SimpleDateFormat (чтобы "мая" получилось по-русски, нужна, соответственно, локаль). Пример: String oldDateString = "2015-05-15"; SimpleDateFormat oldDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); SimpleDateFormat newDateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.getDefault()); Date date = oldDateFormat.parse(oldDateString); String result = newDateFormat.format(date);

Ответ 2



В дополнение к сказанному выше, предлагаю воспользоваться новыми классами из пакета java.time, который появился в Java 8, а не пользоваться давно уже устаревшим java.util.Date String dateString = "2015-05-15"; LocalDate date = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd")); System.out.println(date.format(DateTimeFormatter.ofPattern("dd MMMM yyyy", new Locale("ru"))));

Длина массива в функции с++

#cpp


Как можно в теле функции узнать длину передаваемого массива (для тела цикла)?

#include 

int myfunc(int arr[])
{
    int sum=0, quantity=0;
    for (int i = 0; i < (длина массива (указателя)); i++)
    {
        if (arr[i] > 0)
        {
            quantity++;
            sum += arr[i];
        }
    }
    return sum;
}

int main()
{
   int a[70], b[80], c[65];
   std::cout << myfunc(a);
}

    


Ответы

Ответ 1



Ваш вопрос настолько популярен, что попал даже в FAQ по языку C: [1], [2]. Дело в том, что в параметрах функций массивы «превращаются» в указатели. Поэтому ваше объявление функции ничем не отличается от int myfunc(int* arr) Вы можете проверить, что в вашей функции sizeof(arr) даёт размер указателя (на современных архитектурах обычно 4 или 8). Практический выход: передавайте длину массива отдельным параметром.

Ответ 2



В Си никак. В Си++ можно использовать шаблонную функцию, в которой размер станет параметром шаблона. В любом случае, так не стоит делать, т. к. это не позволит использовать функцию с динамическими массивами. http://ideone.com/HNxwr8 #include using namespace std; template void f(typed (&a)[n]) { for (size_t q=0; q

Ответ 3



В теле функции вы можете узнать длинну массива из передаваемого по соседству аргумента: int foo(int *buffer, const size_t bufferSize) {...} Интересней же вопрос о том как возвращать массив из функции. Для этих целей в C++11 появился std::array, который является ничем иным, как оберткой над обычными статическими буферами, которая, среди прочего, содержит метод size().

Ответ 4



Как вариант - использовать vector и получать размер массива с помощью arr.size()

Ответ 5



Столкнулся с данной проблемой сегодня, но всё-таки нашёл выход. Длинну массива можно определить с помощью такой функции: int getLength(char text[]){ int arrayLength=0; for(int i=0;text[i];i++){ arrayLength++; } return arrayLength; } int main(void){ cout<

Создание объекта класса внутри него же самого

#java


Разбираюсь в Java и возник вопрос: 
Если делаю массив connections статическим и использую его в методе getElementOfArray()
то при System.out.println(getElementOfArray()); он выводит (последний) элемент массива
(что и нужно). Но если я хочу чтобы массив принадлежал объекту а не классу, и создаю
объект ConnectionManagerдля доступа к массиву, то System.out.println(getElementOfArray());
выводит только null.

Вопрос: 


Какой создается объект, при ConnectionManager cm = new ConnectionManager();
Будет ли этот объект начинаться с psvm
Почему все-таки со статическим массивом все проходит хорошо, а при создании объекта
- нет?


Спасибо огромное

public class ConnectionManager {
    private Connection1[] connections = new Connection1[5]; //Массив для Connection1
    private static int counter;

    private void fillArray() {
        for (int i = 0; i < connections.length; i++) {    //Наполняет массив
            connections[i] = Connection1.getInstance();   //элементами Connection1
            counter++;
            System.out.println(connections.getClass() + " Element added");
        }
    }

    static Connection1 getElementOfArray(){
        ConnectionManager cm = new ConnectionManager();     //Cоздание объекта
        if(counter > 0){
            return cm.connections[--counter];
        } else {
            return null;
        }
    }

    public static void main(String[] args) {
        ConnectionManager cm = new ConnectionManager();
        cm.fillArray();
        System.out.println(getElementOfArray());
    }
}

    


Ответы

Ответ 1



У вас создается два объекта ConnectionManager. В методе main один объект, а в методе getElementOfArray другой, соответственно, если массив не статический происходит обращение к разным массивам. Т.е. метод fillArray заполняет массив другого объекта, к которому не происходит обращение. Надеюсь, понятно объяснил =)

Ответ 2



У тебя массив не заполняется. Здесь ты создаешь объект и заполняешь в нем массив: public static void main(String[] args) { ConnectionManager cm = new ConnectionManager(); cm.fillArray(); System.out.println(getElementOfArray()); } А здесь ты создаешь новый объект и ничего в нем не заполняешь: static Connection1 getElementOfArray(){ ConnectionManager cm = new ConnectionManager(); //Cоздание объекта if(counter > 0){ return cm.connections[--counter]; } else { return null; } }

Python, длина строки без учета пробелов

#python


Как можно на Python получить длину строки, но чтобы не считались пробелы? К примеру,
чтобы длина "99 99 99 99" равнялась длине "9999 9999"
    


Ответы

Ответ 1



Можно так: len(str.replace(" ", ""))

Ответ 2



Можно просто вычесть кол-во пробелов: n = len(s) - s.count(" "). Достоинство, что не требуется новую строку создавать: O(1) в памяти—для больших строк может иметь значение в производительности. Если нужно поддерживать произвольные пробельные символы (перевод строки '\n', таб '\t', неразрывный пробел (U+00A0), итд), то можно использовать регулярное выражение, чтобы посчитать кол-во непробельных символов в строке: import re n = len(re.findall(u"\\S", s, flags=re.UNICODE)) ответ близок к n = len(''.join(s.split())) или другому способу, основанному на удалении пробелов из строки. Можно избежать создания нового списка, если использовать finditer(): n = sum(1 for m in re.finditer(u"\\S", s, flags=re.UNICODE) if m) этот код требует O(1)памяти (константа независящая от размера входной строки), но на практике даже для умеренно больших строк он может быть медленнее более жадных вариантов, где память пропорциональна вводу O(n) (решения, использующие список, новую строку).

Ответ 3



len(''.join("99 99 99 99".split())) сравнение быстродействия способов: import timeit, sys, itertools, re, random, string def var1(): return len([s for s in _str if not s == ' ']) def var2(): return len(list(itertools.chain(*_str.split()))) def var3(): return len(''.join(_str.split())) def var4(ln=0): for с in _str: if с != ' ': ln += 1 return ln def var5(): return sum(map(lambda c: int(not(c == ' ')) , _str)) def var6(): return sum(map(lambda c: 1 if c != ' ' else 0, _str)) def var7(): return len(_str.replace(" ", "")) def var8(): return len(_str) - _str.count(" ") def var9(): return len(re.findall(u"\\S", _str, flags=re.UNICODE)) def var10(): return sum(1 for m in re.finditer(u"\\S", _str, flags=re.UNICODE) if m) def print_results(data: dict): # печать результатов одного прохода x = ['average', 'min', 'max'] f = ' {:<12}' * (len(x) + 1) print(f.format('', *x)) for e, (k, v) in enumerate(sorted(data.items(), key=lambda it: it[1][1]), start=1): gv = ('{:f}'.format(g) for g in v) print(f.format('%s %s' % (e, k), *gv)) # начисление "баллов", кто первее, тоиу больше - enumerate for e, (k, v) in enumerate(sorted(data.items(), key=lambda it: it[1][1], reverse=True), start=1): try: best_var[k] += e except KeyError: best_var[k] = e def get_str(size: int, asc: bool, a=5, b=10, i=''): # ascii или ascii+noascii символы asc_ = ''.join(map(chr, range(256))) if asc else string.ascii_letters _str, ln = '', 0 # увеличивать строку, пока размер не станет нужным while ln < size: _str += ' ' + ''.join(random.choice(asc_) for _ in range(random.randint(a, b))) # a, b - регулировать пробелы ln = int(sys.getsizeof(_str)/1024) # инфо о строке ss = _str.split() c = len(ss) l, c, = len(_str), _str.count(' ') w = sum(len(s) for s in ss)/c print('\n~{}Kb, символы {} {}, {} ~ {:.3}%, сред длина слова:{:f}\nby :'.format( ln, l, 'ascii+noascii' if asc else 'ascii', i, c/l*100, w)) return _str if __name__ == '__main__': best_var = {} repeat, count = 5, 1 target = [n for n in globals() if n.startswith('var')] # размеры строк for size in 1, 1024, 1024*10: data = {} # ascii или ascii+noascii строка for asc in True, False: # кол-во пробелов for i, a, b in (['минимум пробелов', 20, 25], ['сред пробелов', 4, 5], ['много пробелов', 1, 2], ['случайно пробелов', 1, 1000]): # сформировать строку _str = get_str(size, asc, a, b, i) # выполнить var функции for n in target: t = timeit.Timer(globals()[n]).repeat(repeat, count) data.update({n: [sum(t)/repeat, min(t), max(t)]}) print_results(data) # вывести результат для строки # вывести баллы print('\n'+'-'*20) for e, (k, v) in enumerate(sorted(best_var.items(), key=lambda kv: kv[1], reverse=True), start=1): print('{} место {:<5} - {} баллов'.format(e, k, v)) out: ~1Kb, символы 989 ascii+noascii, минимум пробелов ~ 4.65%, сред длина слова:19.347826 by : average min max 1 var8 0.000004 0.000003 0.000005 2 var7 0.000006 0.000006 0.000008 3 var3 0.000022 0.000022 0.000025 4 var2 0.000063 0.000054 0.000085 5 var1 0.000124 0.000117 0.000134 6 var4 0.000172 0.000157 0.000187 7 var9 0.000264 0.000157 0.000401 8 var6 0.000235 0.000213 0.000295 9 var10 0.000311 0.000279 0.000343 10 var5 0.000439 0.000389 0.000494 ~1Kb, символы 989 ascii+noascii, сред пробелов ~ 18.4%, сред длина слова:4.252747 by : average min max 1 var8 0.000004 0.000003 0.000004 2 var7 0.000013 0.000012 0.000015 3 var3 0.000031 0.000030 0.000033 4 var2 0.000072 0.000068 0.000081 5 var1 0.000115 0.000111 0.000130 6 var9 0.000145 0.000138 0.000164 7 var4 0.000150 0.000143 0.000165 8 var6 0.000235 0.000213 0.000259 9 var10 0.000267 0.000258 0.000283 10 var5 0.000417 0.000385 0.000468 ~1Kb, символы 987 ascii+noascii, много пробелов ~ 40.7%, сред длина слова:1.375622 by : average min max 1 var8 0.000005 0.000004 0.000006 2 var7 0.000019 0.000018 0.000020 3 var3 0.000038 0.000035 0.000045 4 var2 0.000086 0.000076 0.000112 5 var9 0.000106 0.000098 0.000137 6 var1 0.000120 0.000104 0.000153 7 var4 0.000119 0.000117 0.000123 8 var10 0.000193 0.000178 0.000228 9 var6 0.000228 0.000216 0.000264 10 var5 0.000409 0.000386 0.000447 ~1Kb, символы 1491 ascii+noascii, случайно пробелов ~ 0.738%, сред длина слова:127.818182 by : average min max 1 var8 0.000003 0.000003 0.000004 2 var7 0.000004 0.000004 0.000005 3 var3 0.000027 0.000026 0.000029 4 var2 0.000078 0.000068 0.000109 5 var1 0.000207 0.000201 0.000223 6 var9 0.000247 0.000229 0.000274 7 var4 0.000261 0.000235 0.000312 8 var6 0.000344 0.000319 0.000381 9 var10 0.000459 0.000439 0.000503 10 var5 0.000605 0.000572 0.000640 ~1Kb, символы 1007 ascii, минимум пробелов ~ 4.27%, сред длина слова:22.418605 by : average min max 1 var8 0.000003 0.000003 0.000004 2 var7 0.000006 0.000005 0.000007 3 var3 0.000009 0.000008 0.000010 4 var2 0.000045 0.000040 0.000056 5 var1 0.000139 0.000116 0.000164 6 var9 0.000168 0.000151 0.000187 7 var4 0.000161 0.000151 0.000195 8 var6 0.000229 0.000214 0.000275 9 var10 0.000303 0.000299 0.000314 10 var5 0.000406 0.000383 0.000435 ~1Kb, символы 1001 ascii, сред пробелов ~ 18.0%, сред длина слова:4.561111 by : average min max 1 var8 0.000003 0.000003 0.000004 2 var7 0.000012 0.000011 0.000012 3 var3 0.000019 0.000018 0.000020 4 var2 0.000064 0.000056 0.000091 5 var1 0.000117 0.000105 0.000148 6 var9 0.000142 0.000131 0.000177 7 var4 0.000151 0.000138 0.000182 8 var6 0.000222 0.000213 0.000257 9 var10 0.000265 0.000253 0.000302 10 var5 0.000409 0.000382 0.000451 ~1Kb, символы 1001 ascii, много пробелов ~ 40.0%, сред длина слова:1.502500 by : average min max 1 var8 0.000004 0.000004 0.000005 2 var7 0.000021 0.000020 0.000023 3 var3 0.000033 0.000031 0.000036 4 var2 0.000077 0.000076 0.000081 5 var1 0.000111 0.000099 0.000139 6 var9 0.000110 0.000104 0.000138 7 var4 0.000123 0.000123 0.000124 8 var10 0.000207 0.000197 0.000231 9 var6 0.000234 0.000225 0.000257 10 var5 0.000419 0.000408 0.000441 ~1Kb, символы 1357 ascii, случайно пробелов ~ 0.221%, сред длина слова:451.333333 by : average min max 1 var8 0.000002 0.000002 0.000003 2 var7 0.000003 0.000003 0.000004 3 var3 0.000004 0.000004 0.000005 4 var2 0.000047 0.000044 0.000051 5 var1 0.000161 0.000150 0.000198 6 var9 0.000217 0.000208 0.000246 7 var4 0.000221 0.000210 0.000264 8 var6 0.000302 0.000287 0.000339 9 var10 0.000449 0.000418 0.000470 10 var5 0.000557 0.000517 0.000579 ~1024Kb, символы 1048550 ascii+noascii, минимум пробелов ~ 4.62%, сред длина слова:19.736590 by : average min max 1 var8 0.001648 0.001501 0.001976 2 var7 0.004883 0.004693 0.005125 3 var3 0.020394 0.019550 0.021583 4 var2 0.062164 0.060919 0.063352 5 var1 0.144303 0.135828 0.159222 6 var9 0.178833 0.176592 0.182050 7 var4 0.199833 0.196554 0.205470 8 var6 0.251038 0.246122 0.259824 9 var10 0.335161 0.331631 0.338379 10 var5 0.452639 0.443677 0.466173 ~1024Kb, символы 1048543 ascii+noascii, сред пробелов ~ 18.5%, сред длина слова:4.216881 by : average min max 1 var8 0.002237 0.002042 0.002632 2 var7 0.011823 0.011346 0.012312 3 var3 0.033965 0.032902 0.034526 4 var2 0.084031 0.081243 0.087056 5 var1 0.127829 0.126500 0.129401 6 var9 0.158385 0.154023 0.162586 7 var4 0.180536 0.178501 0.182689 8 var6 0.250811 0.246209 0.255653 9 var10 0.285592 0.283369 0.288488 10 var5 0.454162 0.445657 0.470404 ~1024Kb, символы 1048539 ascii+noascii, много пробелов ~ 40.2%, сред длина слова:1.422101 by : average min max 1 var8 0.002705 0.002559 0.002869 2 var7 0.019173 0.018673 0.019514 3 var3 0.044011 0.041986 0.045685 4 var2 0.092004 0.090061 0.095451 5 var1 0.117086 0.112984 0.122531 6 var9 0.116413 0.113467 0.120848 7 var4 0.152174 0.150377 0.154708 8 var10 0.209933 0.203534 0.214091 9 var6 0.255368 0.251358 0.260667 10 var5 0.449192 0.448205 0.450778 ~1024Kb, символы 1048798 ascii+noascii, случайно пробелов ~ 0.585%, сред длина слова:162.651182 by : average min max 1 var8 0.000781 0.000757 0.000808 2 var7 0.002128 0.001986 0.002363 3 var3 0.014138 0.013806 0.014757 4 var2 0.056218 0.054372 0.059153 5 var1 0.141643 0.137505 0.146517 6 var9 0.188750 0.184148 0.193892 7 var4 0.205695 0.201427 0.209657 8 var6 0.265923 0.258749 0.275960 9 var10 0.344992 0.331897 0.352945 10 var5 0.458320 0.446551 0.482520 ~1024Kb, символы 1048574 ascii, минимум пробелов ~ 4.26%, сред длина слова:22.496930 by : average min max 1 var8 0.001505 0.001434 0.001623 2 var7 0.004558 0.004468 0.004666 3 var3 0.006457 0.006183 0.006700 4 var2 0.045978 0.045481 0.046309 5 var1 0.136627 0.132597 0.143002 6 var9 0.180005 0.172714 0.186334 7 var4 0.195560 0.193381 0.200404 8 var6 0.243767 0.238857 0.246907 9 var10 0.333131 0.328723 0.344105 10 var5 0.439651 0.432095 0.446828 ~1024Kb, символы 1048554 ascii, сред пробелов ~ 18.2%, сред длина слова:4.498592 by : average min max 1 var8 0.002240 0.002156 0.002484 2 var7 0.011550 0.011379 0.011812 3 var3 0.019653 0.018650 0.020899 4 var2 0.064917 0.063636 0.066031 5 var1 0.122076 0.120085 0.123909 6 var9 0.151459 0.148554 0.153874 7 var4 0.178413 0.175546 0.183586 8 var6 0.244974 0.243148 0.246615 9 var10 0.283760 0.279793 0.286557 10 var5 0.444185 0.440670 0.446956 ~1024Kb, символы 1048552 ascii, много пробелов ~ 40.0%, сред длина слова:1.500690 by : average min max 1 var8 0.002606 0.002548 0.002662 2 var7 0.019870 0.019037 0.020380 3 var3 0.033964 0.032878 0.036014 4 var2 0.086213 0.085267 0.087383 5 var1 0.111353 0.109741 0.114724 6 var9 0.112563 0.111011 0.114503 7 var4 0.150361 0.147747 0.152117 8 var10 0.210284 0.209237 0.210916 9 var6 0.250411 0.247752 0.257964 10 var5 0.453721 0.449482 0.457010 ~1024Kb, символы 1048782 ascii, случайно пробелов ~ 0.197%, сред длина слова:506.147969 by : average min max 1 var8 0.000675 0.000646 0.000688 2 var7 0.001583 0.001502 0.001764 3 var3 0.002933 0.002437 0.003270 4 var2 0.044154 0.043674 0.045305 5 var1 0.135097 0.134006 0.136763 6 var9 0.192888 0.190767 0.194671 7 var4 0.200822 0.199586 0.203285 8 var6 0.242871 0.240081 0.246809 9 var10 0.352606 0.344659 0.360171 10 var5 0.440387 0.433437 0.446731 ~10240Kb, символы 10485723 ascii+noascii, минимум пробелов ~ 4.63%, сред длина слова:19.713800 by : average min max 1 var8 0.015642 0.015346 0.016142 2 var7 0.050325 0.049391 0.052610 3 var3 0.210275 0.209163 0.212247 4 var2 0.676338 0.669641 0.682927 5 var1 1.389115 1.368039 1.398386 6 var9 1.821897 1.803700 1.843339 7 var4 1.994729 1.989236 2.000370 8 var6 2.491980 2.478701 2.511737 9 var10 3.274745 3.246427 3.296595 10 var5 4.452530 4.420066 4.492152 ~10240Kb, символы 10485725 ascii+noascii, сред пробелов ~ 18.5%, сред длина слова:4.214989 by : average min max 1 var8 0.022165 0.021553 0.022992 2 var7 0.119701 0.117069 0.122963 3 var3 0.363989 0.359079 0.367310 4 var2 0.885933 0.878938 0.891297 5 var1 1.294802 1.277431 1.311001 6 var9 1.617785 1.611125 1.622048 7 var4 1.818916 1.810579 1.830913 8 var6 2.547398 2.510476 2.582020 9 var10 2.828624 2.809815 2.854437 10 var5 4.480788 4.459377 4.500519 ~10240Kb, символы 10485725 ascii+noascii, много пробелов ~ 40.2%, сред длина слова:1.421055 by : average min max 1 var8 0.028091 0.027061 0.030288 2 var7 0.196943 0.195305 0.199955 3 var3 0.474881 0.461343 0.482662 4 var2 1.008938 0.997040 1.027451 5 var1 1.161058 1.136066 1.171011 6 var9 1.215664 1.164296 1.233138 7 var4 1.543121 1.527249 1.553288 8 var10 2.080153 2.052537 2.101885 9 var6 2.522675 2.515321 2.530619 10 var5 4.563395 4.491082 4.623651 ~10240Kb, символы 10486201 ascii+noascii, случайно пробелов ~ 0.587%, сред длина слова:162.080908 by : average min max 1 var8 0.007789 0.007583 0.008320 2 var7 0.019142 0.018552 0.019879 3 var3 0.165453 0.162585 0.168957 4 var2 0.615963 0.611608 0.620655 5 var1 1.440067 1.421817 1.455080 6 var9 1.899005 1.880525 1.917015 7 var4 2.041620 2.014194 2.117118 8 var6 2.530870 2.444620 2.644582 9 var10 3.375323 3.322056 3.430780 10 var5 4.403470 4.363339 4.462611 ~10240Kb, символы 10485746 ascii, минимум пробелов ~ 4.26%, сред длина слова:22.500840 by : average min max 1 var8 0.015668 0.015235 0.016608 2 var7 0.045992 0.045382 0.046675 3 var3 0.076034 0.074871 0.076558 4 var2 0.534177 0.530063 0.538483 5 var1 1.335994 1.329036 1.342069 6 var9 1.802360 1.792313 1.820512 7 var4 1.954488 1.942886 1.964544 8 var6 2.426299 2.420271 2.436364 9 var10 3.302575 3.286494 3.319168 10 var5 4.434964 4.352420 4.603488 ~10240Kb, символы 10485737 ascii, сред пробелов ~ 18.2%, сред длина слова:4.499947 by : average min max 1 var8 0.021396 0.020741 0.021759 2 var7 0.114626 0.113296 0.115541 3 var3 0.226316 0.222824 0.229988 4 var2 0.728126 0.721727 0.737932 5 var1 1.257480 1.250478 1.265838 6 var9 1.558776 1.552425 1.565449 7 var4 1.782327 1.774427 1.787684 8 var6 2.444034 2.425254 2.466785 9 var10 2.867036 2.849253 2.882571 10 var5 4.398630 4.370555 4.425208 ~10240Kb, символы 10485735 ascii, много пробелов ~ 40.0%, сред длина слова:1.499905 by : average min max 1 var8 0.026567 0.026069 0.027204 2 var7 0.192424 0.190171 0.193983 3 var3 0.377138 0.371293 0.384058 4 var2 0.933870 0.931780 0.936487 5 var1 1.130904 1.126566 1.141807 6 var9 1.166317 1.150050 1.172436 7 var4 1.516546 1.510337 1.525137 8 var10 2.116518 2.085666 2.135315 9 var6 2.488669 2.479040 2.502971 10 var5 4.465629 4.457348 4.473298 ~10240Kb, символы 10485820 ascii, случайно пробелов ~ 0.198%, сред длина слова:502.932141 by : average min max 1 var8 0.007237 0.006813 0.007651 2 var7 0.016183 0.015791 0.016414 3 var3 0.030802 0.029833 0.031738 4 var2 0.468537 0.457903 0.477776 5 var1 1.375179 1.357010 1.388190 6 var9 1.879247 1.867879 1.896920 7 var4 2.016457 1.990694 2.060548 8 var6 2.413361 2.397260 2.420363 9 var10 3.465412 3.430199 3.499782 10 var5 4.380763 4.351999 4.431059 -------------------- 1 место var8 - 240 баллов 2 место var7 - 216 баллов 3 место var3 - 192 баллов 4 место var2 - 168 баллов 5 место var1 - 143 баллов 6 место var9 - 121 баллов 7 место var4 - 96 баллов 8 место var6 - 66 баллов 9 место var10 - 54 баллов 10 место var5 - 24 баллов

Ответ 4



В лоб: len = 0 s = '99 99 99 99' for с in s: if с != ' ': len += 1 print len 8 Функционально-извращенно: s = '99 99 99 99' print sum(map(lambda c: int(not(c == ' ')) , s)) 8 или sum(map(lambda c: 1 if c != ' ' else 0, s))

Как в c# выйти из двойного цикла?

#c_sharp #циклы


Есть двойной цикл for

for (int i = 0; i < 10; i++)
{
   for (int l = 0; l < 20; l++)
   {
       if (....)
       {
           ....
       }
       else
       {
          break;
       }
   }
}


Из второго цикла я выхожу, но как потом сразу выйти из первого цикла ?
    


Ответы

Ответ 1



Для выхода из вложенных циклов со сложной структурой может применяться оператор goto for (int i = 0; i < 10; i++) { for (int l = 0; l < 20; l++) { if (....) { .... } else { goto LoopEnd; } } } LoopEnd: ... Альтернативным решением может стать помещение основного цикла в функцию, и применение оператора return public void Loop() { for (int i = 0; i < 10; i++) { for (int l = 0; l < 20; l++) { if (....) { .... } else { return; } } } }

Ответ 2



Можно использовать дополнительный флаг: var flag = true; for(int i=0; flag && i<10; i++) { for (int l=0; flag && l<20; l++) { if (....) { .... } else { flag = false; break; } } }

Ответ 3



Еще один вариант: for (int i = 0; i < 10; i++) { for (int l = 0; l < 20; l++) { if (false) { System.Console.WriteLine(":)"); } else { i = Int32.MaxValue - 1; break; } } }

WPF Таблица XAML

#c_sharp #mysql #wpf #xaml


Ребят подскажите мне тугому как сделать подобную выгрузку элементов с бд с постраничной
или динамической прокруткой данных? Задача: В базе хранятся фотографии и фио студентов.
Требуется выводить фотографию и под ней ФИО студента.



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

На данный момент инф. берется таким способом. 

    


Ответы

Ответ 1



Окей, ну давайте напишем как это нужно делать. Попробуем сразу сделать из этого MVVM. Начнём с модели. Главное — модель должна стараться абстрагировать от нас то, что у неё под капотом. Имея это в виду, организуем её просто как список модельных объектов в памяти. Внешний код не должен от этого зависеть. Итак: public class StudentModel { public string Name { get; set; } public Uri ImageUri { get; set; } } public class StudentListModel { const string uri = "https://www.gravatar.com/avatar/f81585f940e68c3bab934cc6f59c901e?" + "s=328&d=identicon&r=PG"; public IEnumerable GetAllStudents() => Enumerable.Range(0, 200).Select(n => new StudentModel() { Name = $"Student #{n}", ImageUri = new Uri(uri) }); } Функциональность «получить n-ую страницу» я оставляю на VM, держа в голове, что в реальности у вас вместо IEnumerable будет IQueryable. Если вам хочется сделать репозиторий поверх вашего обращения с базой (например потому, что вы не пользуетесь EF), почему бы и нет. С моделью покамест всё, впиливать базу сюда уж придётся вам лично. Перейдём к VM. Для начала, базовый класс для VM. Если вы пользуетесь каким-нибудь MVVM-фреймворком, он у вас уже есть. Если нет, напишем его. Он должен имплементировать INotifyPropertyChanged: class VM : INotifyPropertyChanged { protected bool Set(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; RaisePropertyChanged(propertyName); return true; } protected void RaisePropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); public event PropertyChangedEventHandler PropertyChanged; } Теперь класс, отвечающий за одного студента. С этим всё просто: class StudentVM : VM { string name; public string Name { get { return name; } set { Set(ref name, value); } } Uri imageUri; public Uri ImageUri { get { return imageUri; } set { Set(ref imageUri, value); } } public StudentVM(string name, Uri uri) { this.name = name; this.imageUri = uri; } } Если вы пишете в соответствии с трендами, и у вас иммутабельные классы, получится проще: class StudentVM : VM { public string Name { get; } public Uri ImageUri { get; } public StudentVM(string name, Uri uri) { this.Name = name; this.ImageUri = uri; } } Дальше — класс, занимающийся списком студентов. Будем писать его по кускам. Начнём. class StudentListVM : VM { Нам нужно свойство, отвечающее за количество страниц. Без него никак. Пишем: int totalPages; public int TotalPages { get { return totalPages; } private set { if (value < 0) throw new ArgumentException(nameof(TotalPages)); Set(ref totalPages, value); } } Пока всё просто. Да, наверняка мы захотим ещё показать в UI что-то особое, если у нас нет ни одного студента, поэтому положим вспомогательное свойство: bool havePages; public bool HavePages { get { return havePages; } private set { Set(ref havePages, value); } } и не забудем установить его в сеттере TotalPages: private set { if (value < 0) throw new ArgumentException(nameof(TotalPages)); Set(ref totalPages, value); HavePages = totalPages > 0; // <--- добавили } Следующий пункт — номер текущей страницы. С ним всё то же самое, только проверок в сеттере побольше. int currentPageNo; public int CurrentPageNo { get { return currentPageNo; } set { if (value < 0) throw new ArgumentException(nameof(CurrentPageNo)); if (value >= TotalPages && HavePages) throw new ArgumentException(nameof(CurrentPageNo)); if (value != 0 && !HavePages) throw new ArgumentException(nameof(CurrentPageNo)); Set(ref currentPageNo, value) } } Теперь, когда текущая страница поменялась, мы должны вычитать новый список студентов. Это нужно сделать в фоне, не блокируя UI-поток. Добавляем в CurrentPageNo set { if (value < 0) throw new ArgumentException(nameof(CurrentPageNo)); if (value >= TotalPages && HavePages) throw new ArgumentException(nameof(CurrentPageNo)); if (value != 0 && !HavePages) throw new ArgumentException(nameof(CurrentPageNo)); if (Set(ref currentPageNo, value)) // если изменения были... PopulateCurrentPage().IgnoreResult(); // IgnoreResult напишем позже } Ещё нужно свойство, хранящее список студентов: IEnumerable currentPage; public IEnumerable CurrentPage { get { return currentPage; } private set { Set(ref currentPage, value); } } и код, занимающийся обновлением. Он сложный. // токен для остановки бегущего обновления CancellationTokenSource populationTaskCts = null; async Task PopulateCurrentPage() { // если старое обновление ещё бежит, отменяем его populationTaskCts?.Cancel(); // начиная с этой точки, старое обновление нам не помешает CurrentPage = null; if (!HavePages) return; using (var cts = new CancellationTokenSource()) { // теперь мы - текущее обновление populationTaskCts = cts; var workPageNo = CurrentPageNo; // может поменяться в процессе try { // асинхронно получаем модельный список var modelPage = await Task.Run(() => GetStudentsFromModel(workPageNo, cts.Token), cts.Token); if (cts.IsCancellationRequested) return; // создаём VM-объекты в UI-потоке var vmPage = modelPage.Select(p => new StudentVM(p.Name, p.ImageUri)) .ToList(); if (cts.IsCancellationRequested) return; // если мы оказались тут, то мы всё ещё текущее обновление Debug.Assert(workPageNo == CurrentPageNo); CurrentPage = vmPage; // и можем присвоить результат } catch (OperationCanceledException) when (cts.IsCancellationRequested) { // ничего не делаем, нас отменили } finally { // если мы текущее обновление, убираем за собой токен if (cts == populationTaskCts) populationTaskCts = null; // в противном случае там чужой токен, его не трогаем } } } Нам ещё нужен экземпляр модели и процедура GetStudentsFromModel, которая будет их вычитывать: StudentListModel model = new StudentListModel(); const int pageSize = 10; IEnumerable GetStudentsFromModel(int pageNo, CancellationToken ct) { // make sure it's materialized on background thread return model.GetAllStudents().Skip(pageNo * pageSize).Take(pageSize).ToList(); } К ней ещё понадобится (позже) подсчёт количества страниц: int GetPageCount(CancellationToken ct) { var studentCount = model.GetAllStudents().Count(); return (int)Math.Ceiling((double)studentCount / pageSize); } Сейчас эти процедуры синхронные, но если ваша модель будет выставлять async-интерфейс (как это делает новый EF), их нужно будет сделать асинхронными. Далее. Нам нужна команда изменения текущей страницы. public ICommand RequestPageChange { get; } И её имплементация: метод, который будет отрабатывать: void OnPageChangeRequest(int newPage) { if (!HavePages) return; if (newPage < 0 || newPage >= TotalPages) return; // log an error? CurrentPageNo = newPage; } Привязывать команду к имплементации придётся в конструкторе. Заодно и заведём его: public StudentListVM() { RequestPageChange = new RelayCommand(OnPageChangeRequest); } (класс RelayCommand есть практически везде, я приведу его позже). Да, нам ещё в конструкторе нужно запустить подсчёт количества страниц и первоначальное заполнение: public StudentListVM() { RequestPageChange = new RelayCommand(OnPageChangeRequest); StartInitialPopulate().IgnoreResult(); } async Task StartInitialPopulate() { TotalPages = await Task.Run(() => GetPageCount(CancellationToken.None)); currentPageNo = 0; await PopulateCurrentPage(); } } Кажется, ничего не забыли. Класс получился слишком большой, возможно, имеет смысл разрефакторить его на мелкие куски. Ещё у нас тут упоминался RelayCommand: public class RelayCommand : ICommand { public RelayCommand(Action onExecute) { OnExecute = onExecute; } public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) => true; public void Execute(object parameter) => OnExecute((T)parameter); readonly Action OnExecute; } и функция IgnoreResult: public static class TaskExtgensions { public static void IgnoreResult(this Task t) { } } На этом с вью-моделью, кажется, всё, перейдём к представлению. Вью-модель прикрепляем к представлению, как описано здесь: App.xaml: App.xaml.cs: using System.Windows; using Pages.View; using Pages.VM; namespace Pages { public partial class App : Application { StudentListVM mainVM = new StudentListVM(); protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); new MainWindow() { DataContext = mainVM }.Show(); } } } Теперь идём в MainWindow.xaml. Начинаем: На нашем мок-апе есть явно две области: нижняя маленькая со списком страниц, и верхняя большая с содержимым текущей страницы. Это напрашивается на Grid: Теперь, верхний элемент. Он показывает список элементов, без текущего элемента и всего такого. Так что это ItemsControl: Теперь, как расположены элементы в нём? Они идут не в столбик, а «перетекают» по горизонтали в следующую строку. Отлично, значит, нам нужно установить в ItemsPanel подходящий контейнер: Как выглядит отдельный элемент? Это не стандартный ToString(), это текст с картинкой. Напишем для этого ItemTemplate: Вроде бы ничего не забыли. Окей, с таблицей справились, теперь нам нужен список страниц. Откуда его взять? У нас по идее есть только количество страниц, нужно его превратить в список при помощи конвертера. Затем, мы ведь не хотим показывать все страницы? Их может быть очень много. Будем показывать первые страницы, последние страницы и страницы вокруг текущей. Засучим рукава и вперёд! Для начала, тип для описания страницы или заполнителя: enum PageEntryType { Normal, Current, Ellipsis } struct PageEntry { public int PageNumber { get; } public PageEntryType Type { get; } public PageEntry(int num, PageEntryType type) { PageNumber = num; Type = type; } } Ну и сам конвертер. Надеюсь, я не напутал с вычислениями. Нам нужен IMultiValueConverter, потому что у нас два входных значения. class PageListConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { int currentPage = (int)values[0]; int numberOfPages = (int)values[1]; return RecalcList(currentPage, numberOfPages); } IEnumerable RecalcList(int currentPage, int numberOfPages) { const int pagesAroundCurrent = 3; // сколько страниц вокруг текущей const int pagesAroundEnd = 2; // сколько страниц по краям var min = Math.Max(0, currentPage - pagesAroundCurrent); var max = Math.Min(numberOfPages - 1, currentPage + pagesAroundCurrent); // перекрывается список вокруг текущей страницы со списком у левого края? bool separateLeftEnd = pagesAroundEnd + 1 < min; if (!separateLeftEnd) min = 0; // перекрывается список вокруг текущей страницы со списком у правого края? bool separateRightEnd = numberOfPages - 1 - pagesAroundEnd - 1 > max; if (!separateRightEnd) max = numberOfPages - 1; if (separateLeftEnd) { for (int n = 0; n < pagesAroundEnd; n++) yield return new PageEntry(n, PageEntryType.Normal); // между списками разрыв - многоточие yield return new PageEntry(-1, PageEntryType.Ellipsis); } for (int n = min; n <= max; n++) yield return new PageEntry(n, (n == currentPage) ? PageEntryType.Current : PageEntryType.Normal); if (separateRightEnd) { // между списками разрыв - многоточие yield return new PageEntry(-1, PageEntryType.Ellipsis); for (int n = numberOfPages - pagesAroundEnd; n < numberOfPages; n++) yield return new PageEntry(n, PageEntryType.Normal); } } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotSupportedException(); } } Отлично, список у нас есть, теперь его нужно показать. Как показывать список? Возвращаемся к нашему недописанному XAML'у. Нам нужен ItemsControl, как обычно. Кладём его во вторую строку и добавим небольшой маргин. В ресурсы положим конвертер а элементы берём из количества страниц и номера текущей, с использованием этого конвертера: Окей, дальше нам нужно эти элементы расположить по горизонтали. Для этого сгодится StackPanel. Саму панель тоже центрируем: Теперь отображение каждого элемента списка. У нас есть три варианта отображения: обыкновенная страница показывается в виде ссылки, текущая — без ссылки, но жирным шрифтом, а на месте для многоточия должно появиться многоточие. Выбор из этих трёх вариантов делаем при помощи привязки Visibility блока к значению нашего элемента через конвертер. Конвертер мы напишем позже, он будет делать видимым только один из трёх нужных элементов. Сам конвертер мы добавим в ресурсы ItemsControl'а: Продолжаем: Располагаем элементы один на другом, видимым будет только один. Первый вариант: нормальное отображение. Нам нужна гиперссылка. По нажатию на неё вызовем обработчик из code-behind. Второй вариант: текущая страница. Вместо ссылки — TextBlock с жирным шрифтом. Ну и третий вариант — просто многоточие. Вот и всё с отображением элемента. Больше в XAML'е делать нечего. Заимплементируем обработчик клика по ссылке. Он лежит в классе MainWindow public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } void OnPageChangeRequest(object sender, RoutedEventArgs e) { Нам нужно где-то взять команду. Чтобы не лазить по DataContext'у, сделаем простой трюк: привяжем эту команду в свободное свойство. Например, в Tag. (Это мы сделаем потом, снова-таки в XAML'е.) var command = (ICommand)Tag; // прочитали оттуда команду if (command == null) return; var hyperlink = (Hyperlink)sender; Номер страницы можно вытащить из DataContext'а гиперссылки. var pageNo = ((PageEntry)hyperlink.DataContext).PageNumber; command.Execute(pageNo); } } Возвращаемся в XAML и дописываем Tag: Последняя недописанная вещь — PageEntryTypeToVisibilityConverter. Он очень простой: public class PageEntryTypeToVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { PageEntryType expectedType = (PageEntryType)parameter; PageEntryType actualType = ((PageEntry)value).Type; return expectedType == actualType ? Visibility.Visible : Visibility.Collapsed; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotSupportedException(); } } Запускаем и получаем: Да, а давайте ещё сделаем так, чтобы при пустом списке нам показывалось какое-то разумное сообщение. Это просто. Возвращаемся в XAML и добавляем ещё один элемент во внешний Grid: Но так этот элемент будет виден всегда, а нам нужно только когда страниц нету. Не проблема, привяжемся к свойству HavePages. Нам нужно сконвертировать его в Visibility. Но стандартный BooleanToVisibilityConverter конвертирует не в ту сторону, в которую нам надо, поэтому украдём конвертер отсюда: public class BooleanConverter : IValueConverter { public BooleanConverter(T trueValue, T falseValue) { OnTrue = trueValue; OnFalse = falseValue; } public T OnTrue { get; set; } public T OnFalse { get; set; } public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (!(value is bool)) return DependencyProperty.UnsetValue; return ((bool)value) ? OnTrue : OnFalse; } public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotSupportedException(); } } public class BooleanToVisibilityConverter : BooleanConverter { public BooleanToVisibilityConverter() : base(Visibility.Visible, Visibility.Collapsed) {} } Теперь можно написать так: Нужно только положить его в ресурсы окна: Дальнейшее наведение красоты — на вас.

Книги по Python [дубликат]

#python #книги


        
             
                
                    
                        
                            This question already has an answer here:
                            
                        
                    
                
                        
                            Книги и учебные ресурсы по Python
                                
                                    (1 ответ)
                                
                        
                                Closed 4 года назад.
            
                    
Решил заняться программированием. Выбрал "питон". Прошу, дайте названия, а лучше
прямую ссылку на мануал. Заранее спасибо.    


Ответы

Ответ 1



Официальная документация по языку Python. Ну и если знаний совсем нет, то ищите книгу Марка Лутца "Изучаем Python" -- одна из лучших (имхо).

Ответ 2



Марк Саммерфилд - "Программирование на Python3", по-моему лучшая из всех что видел.

Ответ 3



Учебник Python 3.1 Справочник по языку Python 3.1 Погружение в Python 3 Справочник по языку Python Питон на русском А вообще ищи в нэте книгу "Программирование на Python 3 Подробное руководство" Марк Саммерфилд.

Ответ 4



Также могу посоветовать книгу Дэвида Бизли "Python. Подробный справочник." Будет отличным дополнением к книге Лутца

Ответ 5



По мне так - Dive Into Python, если в ладах с английским.

Ответ 6



В электронной форме проще всего начать с wikibooks.org - python. Ну, а дальше оттуда по ссылкам.

Востребованность Unix-программистов [закрыт]

#unix #работа


        
             
                
                    
                        
                            Closed. This question is opinion-based. It is not currently
accepting answers.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Want to improve this question? Update the question so
it can be answered with facts and citations by editing this post.
                        
                        Closed 4 года назад.
                                                                                
           
                
        
Кто-нибудь из уважаемой публики может сказать, насколько сегодня на рынке востребованы
специалисты по Linux/Unix программированию?     


Ответы

Ответ 1



Востребованы, зарплата не хуже, чем у windows программистов.

Ответ 2



Unix программисты , в основном восстребованы,я бы сказал в сфере Телекоммуникаций,IP TV,и конечно же , серверных технологиях. Очень высокие ЗП.

Ответ 3



если будете глубоко шарить в теме, то будете востребованы как специалист, вне зависимости от общих тенденций рынка

Ответ 4



Google - 10+ страниц Head Hunter 470 вакансий Habrahabr 6 вакансий Как видите вакансий не мало

Ответ 5



По моим наблюдениям юниксоиды в основном востребованы в крупных корпорациях. Малый и средний в большинстве "сидит" под Windows. Конечно, сфера юниксоидов это серверные технологии, хоть Windows и оттяпал кусок (приличный надо сказать) серверного рынка, но все же Unix там все еще заправляет бал. Лет 20 назад - все было не так: Windows сидел на десктопах, на серверах был Unix, доживали свои дни IBM/360, VAX VMS и проч. Я думаю еще 10-к лет Unix на серверах продержится. Хотя кто его знает, сейчас все так зыбко, текуче. Может через 10 лет и серверов то не останется :)

Ответ 6



Unix/Cи программисты востребован, основные направления серверные компоненты для WEB, телекоммуникации, voice-IP, embed системы. Надо отлично знать все системные вызовы, для многих проектов нужно хорошо знать многопоточность, для WEB сектора - кроме HTTP и HTML, хорошо знать написание сетевых демонов, использование разных алгоритмов поиска, работа с БД для телекоммуникационного сектора стек IP/SIP/SЕP/ICDN и прочие.. ориентироваться и иметь опыт работы с разными БД и NoSQL, знать минимум по алгоритмам всякие там сортикровки и поиск в деревьях. в общем направлений хватает

Классы в ООП

#ооп #классы #java


Как понять, каким образом выделять "классы" при проектировании программы? Я понимаю,
что классы - это существительные, над которыми совершаются действия(методы), но когда
доходит до дела, я теряюсь. Сразу куча "существительных" в голову лезет - в итоге ступор!
Как научиться мыслить классами?    


Ответы

Ответ 1



Немножко неправильно вопрос поставлен: мыслить нужно не классами, а объектами. Есть несколько уровней. Первый уровень - концептуальный. Одна из парадигм программирования гласит, что объект несет полную ответственность за свое поведение и эта ответственность должна быть четка определенна. В первую очередь при рассмотрении задачи, следует определить объект как совокупность неких обязательств. Второй уровень - уровень спецификаций. Это когда у вас уже определенны объекты как совокупность неких обязательств, вы рассматриваете эти объекты как совокупность методов. А третий уровень - уровень реализации. Это когда у вас уже есть объект как совокупность обязательств и вы уже знаете, что должен делать (совокупность методов), вы, собственно, продумываете, содержимое класса. То есть определяете поля, методы, конструкторы. Пример, вокзал. Пассажиры приезжают на вокзал, находят путь с которого отправляется поезд. Поезд приходит в определенное время к определенному пути. Пассажиры садятся в поезд. Поезд везет их в место назначения. Тут можно выделить несколько объектов 1)Пассажир - он обязан приехать на вокзал, узнать путь, прийти на путь в определенное время, сесть в поезд; 2)Поезд - подъехать на определенный путь в определенное время, знать и отвезти пассажиров в место назначения; 3)Вокзал - должен менять таблоид, на котором есть нужная информация для пассажиров. Это мы рассмотрели концептуальный уровень. Мы уже выделили объекты и понимаем как они взаимодействуют между собой. Собственно это был вопрос, поэтому продолжать проектировать не будем.

Ответ 2



Не сказал бы, что класс - это "существительное". Возможно, вы имели ввиду "сущность"? Это ближе к истине. Я бы посоветовал думать о классах как о некотором примитиве, благодаря которому вы можете описать реальную (в понимании мира человеческого) вещь (объект). Например, наиболее простой пример, которым можно показать и классы, и наследование разом - это точка, имеющая только координаты [x, y] (для простоты, возьмем на плоскости). Далее из точки, можно рисовать фигуры, например, окружность, с центром в некоторой точке, собственно к координатам вы добавите просто радиус и по сути этого достаточно, чтобы описать два примитива. Но, этого не достаточно чтобы выполнять действия над примитивами. Здесь вы приступаете к проектированию методов вашего класса. Начнем с точки. Базовые методы (кроме, естественно, конструктора, который задает в простейшем случае координаты точки) будет, например ее движение/перемещение по координатным осям (это могут быть вариации на тему: перерисовка в новом месте или расчет новых координат по какому-то алгоритму, например по формуле y=kx+b). Для окружности, вы уже будете использовать написанные ранее методы для прорисовки центральной точки и точек самой окружности с радиусом R. Т.е проектирование или "выделение" классов сводится к представлению (это ваша задача) описания реального предмета в виде наиболее подходящей (оптимальной) структуры данных + проектирование или "выделение" методов для работы с этими данными. Причем, почему важна оптимальность, вы можете хранить все точки окружности и легко пересчитывать их новые координаты, а можете хранить только центральную точку и радиус, но более сложными (относительно) вычислениями рассчитывать их новое местоположение. Своеобразный компромисс между сложностью вычислений (от которой зависит скорость обработки) и занимаемой памятью.

Ответ 3



Можно еще добавить к ответу: Каждый класс должен нести ответственность только за самого себя и операции, которые он должен выполнять. Также один из принципов ООП - сокрытие данных в классе, которые не нужны другим классам. Т.е. если взять простой пример, предложенный Dex, то представим класс Линия. В нем будут две точки типа целое - x и y. Ну так вот эти точки будут скрыты для других классов. А вычисления все будут выполняться с этими точками строго внутри класса Линия. Ну и позаботиться о том, чтобы из других классов можно было установить x и y. Для этого в классе будут методы установитьX и установитьY. Пример: public class Line { private int x; private int y; public void setX(int x) { this.x = x } public void setY(int y) { this.y = y; } //private методы, производящие все необходимые операции с x и y //... .... ... // public void draw() { //Класс фигуры чертит сам себя } } Теперь, работать с фигурами проще: public static void main() { //ИНициализируем объект класса с устанавливаем данные, нужные ему для работы Line line = new Line(); line.setX(5); line.setY(20); //Теперь делаем то, что от класса нам надо - чертим линию. line.draw(); } P.S. Тут лучше бы делать наследование, но такой пример самый простой.

Ответ 4



Обычно этому нас учат в университетах: Каждый класс должен нести ответственность только за самого себя и операции, которые он должен выполнять. Это правильно, но не всегда верно. Класс это действительно отображение сущности, только не надо воспринимать это утверждение буквально. Предположим у нас есть грузчик и набор разных товаров, разве каждый отдельный товар сам отвечает за свою погрузку? Нет, грузчик сам решает как грузить тот или иной товар учитывая рекомендации на упаковке (если такие вообще имеются, если их нет он решает исходя из собственного опыта). Суть разбития на классы это групировка логично связанного функционала. Иногда для этого достаточно групироки по сущностям, иногда нет. Пример: Групировка по сущностям: interface IDrawable { void paint(); } class Point implements IDrawable {...} class Line implements IDrawable {...} class Square implements IDrawable {...} // использование new Point().paint(); new Line().paint(); new Square().paint(); Групировка по функционалу: class Point {...} class Line {...} class Square {...} class DrawingManager { public void draw(Point p) {...} public void draw(Line l) {...} public void draw(Square s) {...} } // использование new DrawingManager().draw(new Point()); new DrawingManager().draw(new Line()); new DrawingManager().draw(new Square()); У каждого варианта есть свои преимущества и недостатки. В реальных приложениях часто все классы можно условно разделить на 2 группы: Контейнеры данных (классы POJO ака JavaBeans) Контроллеры (выполняют операции над данными)

Скачивание файла через urllib

#python #urllib


Подскажите, пожалуйста, как скачать файл средствами python (urllib) доступный по
http и положить его рядом со скриптом?    


Ответы

Ответ 1



urllib -> urlopen - открывает файл по данной ему ссылке для чтения, далее можете его просто считать read(), открыть файл для бинарной записи, и записать в него то что прочитали по http. Пример скачивания эмблемки: import urllib logo = urllib.urlopen("http://www.google.com/images/srpr/logo3w.png").read() f = open("logo3w.png", "wb") f.write(logo) f.close() Также есть urllib.urlretrieve(url, [filname,[...]]) - по моему его предназначение именно для скачивания. import urllib destination = 'logo3w.png' url = 'http://www.google.com/images/srpr/logo3w.png' urllib.urlretrieve(url, destination)

Ответ 2



#!/usr/bin/env python3 from urllib.request import urlretrieve url = 'http://www.bing.com/az/hprichbg?p=rb/CollaredLorys_ROW927887560.jpg' destination = url.rsplit('/',1)[1] urlretrieve(url, destination) Чтобы сохранить читаемые русские имена, можно использовать более сложный способ вычисления имени файла url2filename(): #!/usr/bin/env python # -*- coding: utf-8 -*- import os import posixpath try: from urlparse import urlsplit from urllib import unquote except ImportError: # Python 3 from urllib.parse import urlsplit, unquote def url2filename(url): """Return basename corresponding to url. >>> print(url2filename('http://example.com/path/to/file%C3%80?opt=1')) fileÀ >>> print(url2filename('http://example.com/slash%2fname')) # '/' in name Traceback (most recent call last): ... ValueError """ urlpath = urlsplit(url).path basename = posixpath.basename(unquote(urlpath)) if (os.path.basename(basename) != basename or unquote(posixpath.basename(urlpath)) != basename): raise ValueError # reject '%2f' or 'dir%5Cbasename.ext' on Windows return basename Пример: local_filename, headers = urlretieve(url, url2filename(url))

Ответ 3



urllib.urlrertieve(url, filename)

Ответ 4



destination = url.rsplit('/',1)[1] - Здесь один момент не учтен, если url заканчивается на / то destination это пустая строка. Можно лимит поставить 2 и проверять длину. Пример: destination = url.rsplit('/',1)[2] if len(destination) == 0: destination = url.rsplit('/',1)[1]

Ответ 5



Отвечу для версии python3, будет так: import urllib.request logo = urllib.request.urlopen("http://www.marseille-tourisme.com/fileadmin/user_upload/plan_mars2013.jpg").read() f = open("plan_mars2013.jpg", "wb") f.write(logo) f.close()

Ответ 6



ответ в две строки) import urllib.request, urllib.parse, urllib.error urllib.request.urlretrieve('http://откуда_качаем.ком', './ложим_в_текущаю_папку')

Явные отличия CMP от TEST

#ассемблер


Я начал изучать устройство одной программы недавно, целиком написанной на ассемблере
(т.е никакие трансляторы в машинный не применялись, как в языках высокого уровня).
Так вот, в ней я очень часто встречаю конструкции вида TEST AL, AL ; TEST EAX, EAX и т.д.

Вот вопрос: почему применяется TEST, а не CMP? Да и какой смысл сравниваться с самим
собой? Насколько я знаю, TEST использует логическое "И" (AND). Проясните, пожалуйста,
в этих деталях я не особо просвещён.
    


Ответы

Ответ 1



Команды вида test reg, reg используется для сравнения значения регистра с нулем. После этой операции флаги нуля, знака и чётности либо устанавливаются, либо сбрасываются. Почему не cmp reg, 0? Потому что в скомпилированном виде test reg, reg на целый байт короче, ну и по скорости наверное разница есть. test эквивалентен побитовому and, за исключением того, что модифицируются только флаги, но не операнды. Обычно это нужно, чтобы узнать, установлены ли определенные биты в регистре. А cmp эквивалентен обыкновенному вычитанию, но аналогично модифицирует флаги, не изменяя операнды.

Ответ 2



CMP Reg1, Reg2 l =2 байта, t = 3 такта, спаривается в любом конвеере TEST Reg1, Reg2 l =2 байта, t = 3 такта, спаривается в любом конвеере CMP Reg, Const l = 3-4 байта t = 4 такта, спаривается в любом конвеере Разница в количестве используемых регистров, в результате оптимизации кода и наборе изменяющихся флагов.Т.к. обычно используется следующий формат: TEST Reg1, Reg1, ну и соответственно логике - TEST сравнение с 0 :)

Ответ 3



Установление флагов после этой короткой инструкции test ax,ax 85C0 , позволяет с легкостью не только читать код, благодаря простоте вида , но и уменьшить процессорные временные затраты (реализация AND (логическое "И") - проще сумматора, на нём резализованного, когда используется CMP (вычитание). В подавляющем большинстве случаев, после проверки на 0 используются команды условного перехода Jcc (в данном случае JE (equal) переход если равны (ZF=1)). mov ax, 0 test ax, ax ; and 0 with 0 je flag_not_set ; always taken mov ax, 1 test ax, ax ; and 1 with 1 je flag_not_set ; not taken Вот схематика на уровне микроинструкций:

Как узнать первую цифру элемента массива?

#java #алгоритм


Друзья, как узнать первую цифру элемента массива? 
С последней  я разобрался, а вот с первой затруднения. 

например, дан массив a=[352, 234,745,853]

вывести 3, 2, 7 ,8
    


Ответы

Ответ 1



Вариант Владимира Мартьянова из комментариев (о преобразовании в строку и выборке символа на первой позиции) хороший. Альтернативно можно делать так: Если число равно нулю, то выводим 0, берём следующее число и снова проверяем. Когда число перестанет быть 0, переходим к пункту 2 Находим от числа десятичный логарифм Отбрасываем мантиссу (получается число, равное разрядности - 1) Возводим 10 в полученную степень Отбрасываем мантиссу (потому что Math.pow возвращает double) Делим исходное число на полученное в пункте 5 (получается первая цифра) Такой код: int a[] = {352, 2354,745,853}; for (int i : a) { if (i==0) { System.out.println(0); continue; } if ( i == Integer.MIN_VALUE ) { System.out.println(2); continue; } System.out.println(i / (int)Math.pow(10, ((int)(Math.log10(Math.abs(i)))))); } Output: 3 2 7 8 UPDATE Как подсказал @VladD, нужно отдельно рассмотреть случай с Integer.MIN_VALUE. Дело в том, что Math.abs при i < 0 возвращает -i, а для int это уже выход за пределы 2147483647. Поэтому число возвращается на свою отрицательную позицию.

Ответ 2



Еще один вариант: Проверяем, превышает ли число 10 (включительно) Если да, делим на 10 без остатка и GOTO 1. Если нет, выводим как результат. Код: int a[] = {352, 2354, 745, 853}; for (int i : a) { // если число может быть отрицательным, добавляем следующую строку. i = Math.abs(i) while (i >= 10) { i = i / 10; } System.out.println(i); } 3 2 7 8 Я надеюсь, выводить в одну строку и с рандомными запятыми (3, 2, 7 ,8) это не обязательное требование? =)

Ответ 3



Реализация по мотивам Integer.toString и компании. В принципе, тот же логарифм, но по таблице. final static int[] placements = new int[] { 0, 9, 99, 999, 9_999, 99_999, 999_999, 9_999_999, 99_999_999, 999_999_999, Integer.MAX_VALUE }; static int firstDigit( int number ) { // т.к. Math.abs( Integer.MIN_VALUE ) == Integer.MIN_VALUE // выносим в отдельную проверку if ( number == Integer.MIN_VALUE ) return 2; number = Math.abs( number ); int position = 1; while ( number > placements[position] ) { position++; } return number / (placements[position-1]+1); } public static void main(String args[]) { int a[] = {352, 2354, 745, 853}; // Ня! Стримы! System.out.println( Arrays.stream( a ).map( n -> firstDigit( n ) ) .mapToObj( Integer::toString ).collect( Collectors.joining( ", " ) ) ); }

sizeof для символа кириллицы

#cpp #c #sizeof


Я провел несколько экспериментов, но объяснить почему это так работает я не смог

Пример 1:

#include 
int main() {
    /// латиница
    printf("\n%d",sizeof('a')); /// 1
    /// кириллица
    printf("\n%d",sizeof('ф')); /// 4
    return 0;
}


Пример 2:

#include 
int main() {
    char a = 'a'; /// латиница
    char b = 'ф'; /// кириллица
    printf("\n%d",sizeof(a)); /// 1
    printf("\n%d",sizeof(b)); /// 1
    return 0;
}


Вообще ничего не понимаю объясните!
P.S Компилятор g++
    


Ответы

Ответ 1



Символьные (и строковые) литералы в коде программы так или иначе переводятся компилятором в последовательность байт. Правило этого преобразования зависит от кодировки исходника (как уже упоминали другие участники), но может зависеть и ещё от ряда факторов (см. ответ на другой вопрос). Следует заметить, что оба варианта Вашего кода при попытке компиляции компилятором clang приводят к ошибке: error: character too large for enclosing character literal type char b = 'ф'; /// кириллица А используемый Вами gcc даёт пару предупреждений для строки с буквой ф: warning: multi-character character constant [-Wmultichar] warning: overflow in implicit constant conversion [-Woverflow] Первое говорит об использовании мультисимвольного литерала (что поддерживается не всеми компиляторами). Второе - о том, что этот литерал не помещается в char. Т.е. тип 'ф' компилятором был интерпретирован как нечто большее, чем char, и, как уже упоминалось в цитате из ответа @Harry, этот тип есть int: ... has type int, and has an implementation-defined value. Исходя из вышесказанного, можно сделать вывод: 4 (пример 1) получается, т.к. мультисимвольный литерал не усекается и его размер равен размеру int, т.е. sizeof(int) == 4. 1 (пример 2) получается, т.к. мультисимвольный литерал был усечён до типа char при инициализации переменной b, а sizeof(char) == 1 по определению. Отвечу здесь и на Ваш комментарий к другому сообщению: я представлял себе многобайтовый литерал как один символ из сложной кодировки допустим 'ф' (UTF-8) а это 2 байта выходит мы можем по вашим словам записать не более 2х 'ф'...несостыковочка с 4мя символами Записать более 2х 'ф' у Вас действительно не получится. #include int main() { printf("\n%d",sizeof('ффф')); } warning: character constant too long for its type Т.е. фактически происходит усечение значения до sizeof(int). Но если будет использован строковый литерал, то для хранения ф вполне может хватить двух байт: #include int main() { const char c[] = "ф"; printf("%ld\n", sizeof(c)); } 3 Выводит число 3, т.к. 1 байт отводится под терминирующий ноль.

Ответ 2



sizeof - формально не функция, а оператор, который еще во время компиляции дает размер типа - т.е. сколько памяти требуется для хранения переменной данного типа. Судя по тому, что для латинского литерала 'a' вы получили значение 1, вы компилируете не как C, а как C++! В чистом C литерал символа приводится к типу int, и вы бы получили 4. Приходится также полагать, что исходник у вас сохранен как utf-8, например, так что кириллица раскрывается в нечто большее, чем char, и это нечто приводится к int и дает 4. Последние же строки получают не литерал, а переменную типа char, а для нее в C++ однозначно - sizeof(char) == 1. Вот и все... P.S. Поскольку некоторые настаивают... :) Из стандарта о символьных литералах: An ordinary character literal that contains a single c-char representable in the execution character set has type char, with value equal to the numerical value of the encoding of the c-char in the execution character set. An ordinary character literal that contains more than one c-char is a multicharacter literal. A multicharacter literal, or an ordinary character literal containing a single c-char not representable in the execution character set, is conditionally-supported, has type int, and has an implementation-defined value.

Ответ 3



Тип однобайтового символьного литерала 'q' - это char, sizeof(char) равен 1. Тип многобайтового символьного литерала 'qq' - это int, sizeof(int) это например 4. Если исходники сохраняются в кодировке utf-8, то литерал 'ф' это два байта, он эквивалентен '\xd1\x84'. Соответственно его тип - int.