Здравствуйте.
Подскажите, как написать обобщённый метод чтения данных из файла. Например, в одном
случае нужно считать строки, в другом - целые числа.
Как написать метод типа такого:
public static List readFromFile(Path pathIn, TypeValue typeValue){...};
Корректен ли такой код:
public static List readFromFile(Path pathIn, TypeValue typeValue){
try(Scanner in = new Scanner(pathIn)) {
if (typeValue == TypeValue.typeInt) {
List list = new ArrayList<>();
while (in.hasNextInt()) {
list.add(in.nextInt());
}
return list;
} else {
List list = Files.readAllLines(pathIn);
return list;
}
} catch (IOException e){
return null;
}
}
Здесь pathIn - путь к файлу с данными, typeValue - флаг для обозначения данных (Integer,
String и т.д.).
Смущает, что возвращается не параметризованный List. Как вообще решается задача чтения
из файла, если формат данных может быть разным - Integer, Double, String и т.д.? Или
следует писать для каждого типа данных свой код для чтения? Как-то громоздко тогда
получается.
Ответы
Ответ 1 Функционал из Java 8 Stream & Lambda позволяет передавать в метод функциональный
интерфейс, который будет применен к потоку данных:
public void start() throws IOException {
Path path = Paths.get("test");
List resultStringList = readFile(path, Function.identity());
List resultIntList = readFile(path, Integer::parseInt);
}
public List readFile(Path path, Function func) throws IOException {
return Files.lines(path)
.map(func)
.collect(Collectors.toList());
}
}
Ответ 2 Или следует писать для каждого типа данных свой код для чтения?
Не самый плохой вариант: написать отдельные методы для каждого типа (в Scanner, например,
так и сделали) .
Как-то громоздко тогда получается.
В Вашем варианте вместо нескольких коротких методов используется один, в котором
в одном большом if будет код всех этих методов.
Альтернатива
Можно обернуть метод в интерфейс и применить полиморфизм:
//интерфейс
interface ListReader {
List read(String path);
}
//все общие функции вынесем в отдельный базовый класс
abstract class BaseListReader implements ListReader {
@Override
public List read(String path) {
try (Scanner in = new Scanner(path)) {
List list = new ArrayList<>();
while (hasNext(in)) {
list.add(next(in));
}
return list;
} catch (IOException e) {
return null;
}
}
abstract boolean hasNext(Scanner in) throws IOException;
abstract T next(Scanner in) throws IOException;
}
class IntListReader extends BaseListReader {
@Override
boolean hasNext(Scanner in) throws IOException {
return in.hasNextInt();
}
@Override
Integer next(Scanner in) throws IOException {
return in.nextInt();
}
}
class StringListReader extends BaseListReader {
@Override
boolean hasNext(Scanner in) throws IOException {
return in.hasNext();
}
@Override
String next(Scanner in) throws IOException {
return in.nextLine();
}
}
Затем создать фабрику:
//Метод для создания
public ListReader createReader(Class clazz) {
if (clazz == Integer.class) {
return new IntListReader();
} else if (clazz == String.class) {
return new StringListReader();
}
throw new IllegalArgumentException("clazz");
}
В такой реализации обработка разных типов будет отделена друг от друга и от классов-клиентов
(публичным может быть только интерфейс ListReader). Это позволит протеститровать их
отдельно от других классов приложения/использовать класы повторно.
Насколько это оправдано нужно решать по ситуации. Если код будет использован один
раз, требования к нему изменяться не будут и нет строгих требований к качеству (покрытие
тестами, ограничение сложности методов), то может быть достаточно просто разбить на
отдельные методы.
Смущает, что возвращается не параметризованный List
Эта проблема не решена (возвращается не параметризованный ListReader). Решение зависит
от того как используется результат метода. Если полученный список обрабатывается как
List то метод можно оставить непараметризованным. Если в дальнейшем объекты
из списка приводятся к типу, то стоить рассмотреть возможность параметризации фабрик
и клиентского кода.
#java #android #sqlite
Есть две таблицы, в главной таблице есть столбец name, который является ключем для
дочерней таблицы.
Когда я обновляю name, делаю это так:
// перезаписываем данные обьекта
public static void reloadObject(String oldName, String newName, String description,
String date, Context context) {
ContentValues cv = new ContentValues();
ObjectDB objectDB = new ObjectDB(context);
SQLiteDatabase db = objectDB.getWritableDatabase();
cv.put(ObjectDB.objColumn.NAME, newName);
cv.put(ObjectDB.objColumn.DESCRIPTION, description);
cv.put(ObjectDB.objColumn.START_DATE, date);
db.update(ObjectDB.dbTab.OBJECT, cv, ObjectDB.objColumn.NAME + " = ?", new String[]{oldName});
db.close();
}
в дочерней таблице этот столбец не обновляется, хотя в настройках таблицы указано:
[object] TEXT REFERENCES geology_object([name]) ON DELETE RESTRICT ON UPDATE CASCADE,
Если обновить значение name в программе SQLite Expert Personal то все корректно обновляется.
Использую готовую базу данных и вставляю ее в проект с помощью Android SQLiteAssetHelper
Ответы
Ответ 1 Нашел ответ на свой вопрос, может кому-то пригодится.
Нужно было вставить эту строчку:
db.setForeignKeyConstraintsEnabled(true);
перед
db.update(ObjectDB.dbTab.OBJECT, cv, ObjectDB.objColumn.NAME + " = ?", new String[]{oldName});
и все заработало.
Ответ 2 Я применяю немного другой способ. Перегружаю метод SQLiteOpenHelper.onOpen()
@Override
public void onOpen(SQLiteDatabase database) {
super.onOpen(database);
database.execSQL("PRAGMA foreign_keys=ON;");
}
тоже работает, причем метод более универсальный, поскольку setForeignKeyConstraintsEnabled()
работает только с API 16
#sql #sql_server
После добавления индекса они "материализуются" ?
Если да, то каким образом происходит обновление представления? Например, запрос начал
возвращать дополнительные строки. Они пересоздаются по какому-то расписанию?
Имеет ли разницу использовать индексированые представления на часто меняющихся данных
или данных, которые редко изменяются?
Ответы
Ответ 1 После добавления индекса они "материализуются" ?
Именно так. Добавление уникального кластерного индекса материализует данные, возвращаемые
представлением, в этот самый кластерный индекс (т.е., по существу, в отдельную таблицу).
Если да, то каким образом происходит обновление представления?
Например, запрос начал возвращать дополнительные строки. Они
пересоздаются по какому-то расписанию?
Обновление материализованного представления происходит синхронно с изменением данных
в таблицах, на которых оно основано, и инкрементально (индексы представлений не перестраиваются
полностью каждый раз при изменении данных, а дополняются или модифицируются).
Представьте, что имеется обычная таблица с дополнительным индексом. Если добавить
строк в таблицу, то индекс обновится в соответствии с данными таблицы. Механизм обновления
данных материализованного представления аналогичен механизму обновления данных в индексе
из данных таблицы.
Поэтому
Имеет ли разницу использовать индексированные представления на часто
меняющихся данных или данных, которые редко изменяются?
да, использование индексированных представлений на часто меняющихся данных, как правило,
менее желательно, чем на редко меняющихся, т.к. наличие индексированного представления
будет замедлять изменение этих данных.
Достаточно большое число специальных требований и ограничений, которым должно удовлетворять
представление, чтобы его можно было материализовать (привязка к схеме, требования детерминированности,
невозможность использования неаддитивных агрегирующих функций), связано именно с реализацией
материализованных представлений в виде индекса и инкрементальностью обновления данных
в них.
#c_sharp #visual_studio
После полного build solution, повторный build один проект пересобирает. Из за чего
такое может быть?
Ответы
Ответ 1 По умолчанию Visual Studio собирает только те проеткты, в которых были изменения
во входных файлах. Т.е. если вы нажмете Build два раза подряд, то в первый раз вы получите
сообщение вида
========== Build: 3 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
Во второй раз вы скорее всего получите сообщение вида:
========== Build: 0 succeeded, 0 failed, 3 up-to-date, 0 skipped ==========
В некоторых случаях проект может перебилдовываться даже если во входных файлах не
было изменений:
Некоторые типы проектов просто не поддерживают up to date check. Например, SQL Server
Database project будет собираться при каждой сборке решения.
Кроме того, студия всегда считает не up-to-date те проекты, в которых есть файлы
с Copy to Output Directory' выставленном в 'Copy always'.
Выяснить точную причину, по которой конкретный проект попадает под билд можно выставив
Tools → Options → Projects and Solutions → MSBuild project build output verbosity в
Diagnostics. На этом уровне детализации студия выведет причину билда в окно Output,
примерно в таком виде:
1>Project 'ConsoleApp37' is not up to date. Project item 'C:\...\TextFile1.txt'
has 'Copy to Output Directory' attribute set to 'Copy always'.
Ответ 2 Потому что в файле проекта была строчка
Always
#c_sharp #entity_framework #linq
Изучая различия между LINQ To Entites и LINQ To Objects в EntityFramework - столкнулся
с интересной вещью :
var phones = db.Phones.Where(p=> p.CompanyId == 1).ToList().Where(p=> p.Id<10);
Здесь используются два метода Where, но их реализация будет различной. В первом случае,
db.Phones.Where(p=> p.CompanyId == 1) транслируется в выражение SQL, которое было рассмотрено
выше. Далее метод ToList() по результатам запроса создает список в памяти компьютера.
После этого мы уже имеем дело со списком в памяти, а не с базой данных. И далее вызов
Where(p=> p.Id<10) будет обращаться к списку в памяти и будет представлять Linq to Object.
И мне стало интересно : А не проще ли просто получать нужное значение из БД путем
простого обращения через LINQ не используя при этом LINQ To Objects?
Ведь запрос в даном случае будет выглядеть так :
var phones = db.Phones
.Where(p => p.CompanyId==1 &&
p.TelephoneId<10)
Хотелось бы узнать какой подход в данном случае будем эффективней и почему?
Ответы
Ответ 1 Смотрите. Базы данных предназначены, кроме всего прочего, и для того, чтобы быстро
и эффективно работать с большими объёмами данных. Например, базы данных легко справляются
с выборкой из таблиц, больших по размеру, чем оперативная память. А вот получение целой
такой таблицы в память с целью последующей фильтрации уже провалится по перерасходу памяти.
Также и фильтрация в базе данных может быть очень быстрой, т. к. если у неё есть
индекс на фильтруемое поле, она может совместить фильтрацию с выборкой. (А особо умные
базы данных могут, исходя из запросов, такой индекс и выстроить сами.) Если индекса
нет, то всё равно польза от фильтрации на стороне базы в том, что выброшенные фильтром
данные не нужно перегонять из базы в программу, и не нужно создавать их в основной
программе только для того, чтобы тут же выбросить.
Поэтому обычно имеет смысл те части запроса, которые можно выполнить в базе данных
(это та часть, при которой вы остаётесь в рамках IQueryable), выполнять на ней.
(Я не уверен, относится ли эта рекомендация к вложенным подзапросам, пускай лучше
специалисты по базам данных поправят меня.)
К сожалению, скорость операций на базе данных имеет и обратную сторону: не все операции
можно выполнить на базе данных, поэтому промежуточные результаты запроса приходится
материализовать (то есть, получать из базы и загружать в память), используя ToList
или AsEnumerable, и «дорабатывать напильником» в самой программе.
«Умения» различных баз данных отличаются между собой. Обычно база данных должна уметь
фильтровать не только по равенству поля значению, но и уметь сравнивать с константой.
Судя по всему, либо вам попался код для менее продвинутой базы данных (да, абстракции
протекают), либо автор кода ошибся. Либо это «костыль» под какой-нибудь баг. Если сравнение
возможно выполнить на базе данных, его стоит именно там и выполнять.
Ответ 2 В общем случае, вы конечно правы, проще получить одним запросом к БД, чем фильтровать
потом в оперативной памяти. Но тут есть несколько нюансов.
Во-первых мы должны учитывать, что в базе данных таблица несколько более сложна чем
мы можем видеть в нашем коде, с ней связаны еще такие сущности как и индексы, триггеры
и тд... Поэтому добавление какого либо дополнительного условия, может порождать "плохой"
план запроса с полным перебором довольно больших объемов данных (например если Id входит
только в составной индекс, да, для поля с таким названием это было бы странно, но...
). В таком случае, иногда, проще выбрать только небольшую часть данных, материализовать
их (ToList()), и отфильтровать их уже в памяти, вместо проведения рефакторинга всей БД.
Во-вторых Phones может быть не таблицей, а представлением, и планы запросов станут
в таком случае еще сложнее.
#android_studio
Не могу отключить сворачивание кода в студии. Нашел только хот-кей. Но каждый раз
нажимать надоедает. Отключение "closures" не помогает.
Ответы
Ответ 1 File -> Settings.. -> Editor -> General -> Code Folding
Галочки в секции Collapse by Default указывают, какие части кода сворачивать по умолчанию.
#javascript #html #jquery #css #css3
Приветствую.
На сайте https://webgradients.com/ если кликнуть по любому из градиентов - он развернется
на весь экран с анимацией. Как сделать подобный эффект для блока?
Заметил, что при клике в body добавляется класс state-fixed к уже существующему state-show,
но разобраться с js-кодом, когда он еще и сжат, мне сложно. Помогите пожалуйста.
Ответы
Ответ 1 Я бы сделал так:
var ripple = $('.ripple'), // "капля"
rippleSize = screenProp(), // размер капли
posLeft = 0,
posTop = 0;
ripple.outerWidth(rippleSize * 2).outerHeight(rippleSize * 2); // задаем капле размер
в 2 раза больше размера экрана, чтобы "покрыть" всю видимую область страницы
$('.gradient').click(function(e) { // клик на градиент
$('body').addClass('fixed'); // блокируем прокрутку экрана
posLeft = e.pageX - rippleSize - $(window).scrollLeft(); // положение капли слева
posTop = e.pageY - rippleSize - $(window).scrollTop(); // положение капли сверху
var gradient = $(this).attr('data-gradient-css'); // получаем код градиента
ripple.addClass('ripple--active').css({ // добавляем класс для увеличения и прописываем
стили
'left': posLeft + 'px',
'top': posTop + 'px',
'background-image': gradient
});
setTimeout(function() { // после увеличения
ripple.addClass('ripple--complete'); // добавляем класс, который выровнит каплю
точно по краям экрана
}, 500); // время анимации увеличения
});
ripple.on('click', function() { // при клике на каплю
if (ripple.hasClass('ripple--complete')) { // если анимация закончилась
$('body').removeClass('fixed'); // возвращаем странице прокрутку
ripple.removeClass('ripple--complete ripple--active'); // удаляем классы
}
});
$(window).on('resize', function() { // при ресайзе окна
rippleSize = screenProp(); // пересчитываем размер капли
ripple.outerWidth(rippleSize * 2).outerHeight(rippleSize * 2); // и задаем ей полученные
значения
});
// функция для определения максимального значения из высоты и ширины экрана
function screenProp() {
if ($(window).width() > $(window).height()) {
return $(window).width();
} else {
return $(window).height();
}
}
html,
body {
padding: 0;
margin: 0;
}
body {
overflow-x: hidden;
overflow-y: auto;
}
body.fixed {
overflow: hidden;
}
* {
box-sizing: border-box;
}
.container {
display: flex;
flex-wrap: wrap;
}
.block {
width: 31%;
margin: 0 1%;
background: #fff;
border-radius: 10px;
padding: 20px;
}
.gradient {
width: 100%;
height: 0;
padding-bottom: 100%;
border-radius: 100%;
background: #000;
cursor: url(https://i.imgur.com/wz8iY4B.png) 16 16, pointer;
}
.ripple {
width: 200%;
height: 200%;
position: fixed;
z-index: 9999;
transition: transform .5s linear;
transform: scale(0);
transform-origin: center;
border-radius: 100%;
cursor: url(https://i.imgur.com/NRHTafk.png) 16 16, crosshair;
}
.ripple--active {
transform: scale(1);
}
.ripple--complete {
left: 0!important;
top: 0!important;
width: 100%!important;
height: 100%!important;
border-radius: 0!important;
}
#php #symfony2 #symfony #symfony3
Вылил сайт на хостинг и появилась ошибка подключения к базе данных.
You have requested a non-existent parameter "database_name". Did you mean one of
these: database
Локально всё работает нормально. В чём может быть ошибка?
Ответы
Ответ 1 Скорее всего неправильно задан конфиг в parameters.yml либо в config.yml.
в parameters.yml добавьте:
parameters:
database_host: YOUR_HOST
database_port: 3306
database_name: DB_NAME
database_user: DB_USER
database_password: DB_PASS
а в config.yml добавьте подключение к доктрине
doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
charset: UTF8
#java
Наткнулся на такой термин - "статический полиформизм". Не знал про такое сочетание.
В гугле особо ничего не нашел.
Кто бы мог дать обьяснение термина + пример?
Ответы
Ответ 1 Этим умным словосочетанием обозначают обычную перегрузку методов. Не ту, что имеет
место в классах-наследниках, помечаемых словом override, а что-то наподобие:
class Foo {
public void some() {
// какой-то код
}
public void some(int parameter) {
// какой-то код
}
}
#android #rest #retrofit #rxjava
Здравствуйте. Недавно начал разбираться с RxJava. Что-то тяжело пока дается...
Есть сервер на котором есть приватные чаты(тет-а-тет) и групповые.
Посредством Rest запроса на сервер нужно выудить следующую инфу оттуда:
Все существующие чаты и диалоги:
Observable> chats = apiService.getChats();
Observable> dialogs = apiService.getDialogs();
Объекты Chat и Dialog содержат переменные:
int unreadMessagesCount (количество непрочитанных сообщений);
int id (по этому id запрашивается список сообщений из чата)
Запросы на список сообщений
Observable> dialogMessages = apiService.getDialogMessages(String id);
Observable> chatMessages = apiService.getChatMessages(String id);
Как в этом случае более грамотно составить запросы используя RxJava, чтобы опросить
все чаты и диалоги на предмет новых сообщений и затем получить эти сообщения в один список?
Ответы
Ответ 1 Например как-то так:
Получаем массив чатов.
Преобразуем массив оных в очередь объектов Chat.
Получаем детали каждого.
Результат преобразовываем обратно в массив:.
apiService.getChats()
.from(Observable::from)
.flatMap(chat -> apiService.getChatMessages(chat.id))
.toList()
.subscribe(System::out);
Если без лямбд, то from(Observable::from) можно переписать вот такой ужасной конструкцией:
.flatMap(new Func1, Observable>() {
@Override
public Observable call(List chats) {
return Observable.from(chats);
}
})
#php #javascript #http #post
Закрыт. Этот вопрос не по теме. Ответы на него в данный
момент не принимаются.
Хотите улучшить этот вопрос? Update the question so it's
on-topic for Stack Overflow на русском.
Закрыт 2 года назад.
Можно ли как то перевести это в PHP, если да то подскажите пожалуйста как?
function request(func, params, onSuccess) {
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://FF2:7000/$gate/request', true);
xhr.setRequestHeader("pro-verba-esb-queue", "IM");
xhr.setRequestHeader("x-function", encodeURI(func));
xhr.onreadystatechange = function() {
if (this.readyState != 4) return;
if (this.status != 200) {
alert( 'ошибка: ' + (this.status ? this.statusText : 'запрос не удался') );
return;
}
onSuccess(this.responseText);
}
xhr.send(JSON.stringify(params));
}
Ответы
Ответ 1 Воспользуйтесь curl
$url = 'http://FF2:7000/$gate/request';
$headers = array(
'pro-verba-esb-queue: IM',
'x-function: '+encodeURI(func)
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, count($params));
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
echo $result;
Ответ 2 Используй библиотеку Guzzle. Вот ссылка на нее http://guzzlephp.org. Приведу небольшой
пример, а для большего пониманий прочитай документацию
$client = new GuzzleHttp\Client();
$client->request('POST', 'http://FF2:7000/$gate/request', [
'headers' => [
'pro-verba-esb-queue' => 'IM',
'x-function' => ""
]
]);
#java #linux #jar
Добрый день.
У меня имеется некий сервер на Debian на котором я запускаю некие Java файлы. Для
их запуска используется Java, которая уже установлена в систему.
Собственно вопрос в том, а могу ли я скачать другую версию Java в какую-то папку
и уже запускать мои файлы не с помощью системной версии Java, а с той, которую скачали
отдельно? Если да - то какой командой. Спасибо
Ответы
Ответ 1 Да, разумеется можете.
Допустим, вы запускаете файл с помощью системной java так:
java -jar myapp.jar
тогда если скачав другую версию, например в директорию /home/user/downloads/jdk/
вы можете запускать свой файл так:
/home/user/downloads/jdk/bin/java -jar myapp.jar
#java #регулярные_выражения #строки
К примеру есть вот такая строка:
String text = "The urn was then carried for several rounds around the cremation
site, for the last leg of the procession."
Мне надо разбить её на слова, удалив при этом все знаки препинания и спецсимволы,
а слова поместить в список.
ArrayList words = new ArrayList<>();
String word = text.replaceAll(",", " "); - тут, насколько я понимаю, надо
делать регулярное выражение ? Или можно без него удалить знаки препинания и спецсимволы ?
Ответы
Ответ 1 Можно разбить строку с помощью регулярного выражения.
String text = "The urn was then carried for several rounds around the cremation site,
for the last leg of the procession.";
String[] results = text.split("\\W+");
System.out.println(Arrays.toString(results));
// [The, urn, was, then, carried, for, several, rounds, around, the, cremation, site,
for, the, last, leg, of, the, procession]
Чтобы \\W+ "понимал" Юникод, добавьте (?U) перед регулярным выражением (чтобы не
удалялись русские и другие буквы), "(?U)\\W+".
Обратите внимание, что \\W+ не найдёт знака подчёркивания _ и если его надо найти,
используйте "[\\W_]+".
См. демо онлайн
Можно найти все буквы Юникода (\p{L}) и ASCII-цифры ([0-9]) с помощью
String text = "The urn was then carried for several rounds around the cremation site,
for the last leg of the procession. И ещё...";
Pattern pattern = Pattern.compile("[\\p{L}0-9]+");
Matcher matcher = pattern.matcher(text);
List result = new ArrayList<>();
while (matcher.find()){
result.add(matcher.group(0));
}
System.out.println(result);
// [The, urn, was, then, carried, for, several, rounds, around, the, cremation, site,
for, the, last, leg, of, the, procession, И, ещё]
Ещё одно Java-демо
#linux #многопоточность #hardware
Здравствуйте, читаю "Системное программирование" Роберта Лава, он пишет про fsync(),
O_SYNC, но не понятно о назначении этих функций...
Где необходимы вызовы этих функций? Если б это было нужно всегда, то синхронизация
бы была по дефолту установлена.
Цитата из книжки.
Налицо огромное увеличение издержек, поэтому синхронизированный ввод-вывод следует
использовать только при отсутствии альтернатив.
Со сколькими параллельными операциями ввода / вывода может работать жесткий диск?
Ну т.е. хочу я в 1000 нитях параллельно читать или писать в разные файлы на диске,
будет ли толк, или начнет всё тормозить (имеется ввиду не из-за переключения контекста,
а из-за каких-то причин с самим диском)?
Ответы
Ответ 1 fsync и его подвиды требуются, когда приложение хочет получить гарантию, что данные
уже записаны на физический диск, а не будут записаны на диск.
Впрочем, начну лучше со второго вопроса:
со сколькими параллельными операциями ввода/вывода может работать жесткий диск?
С одной. Потому что внутри HDD только один блок головок чтения-записи. И из-за ограничений
физических законов нашей вселенной этот блок может одновременно находиться только над
одним местом магнитного диска.
И следующее механическое ограничение - магнитные диски вращаются с постоянной скоростью,
а читать-писать можно только в одном месте. Значит если мы хотим прочитать сектора
в разных местах диска нам требуется:
спозиционировать на эту дорожку блок головок чтения-записи
дождаться, пока требуемый сектор не окажется под головкой
Простым математическим подсчётом получаем механический предел в 120 операций в секунду
для 7200 rpm дисков (с частотой вращения 7200 оборотов в минуту). Будет меньше операций
если надо читать с разных областей диска, т.к. перемещение магнитной головки штука
медленная мало того из-за того что механическая операция но должна осуществляться точно
(речь о микрометрах), так ещё и в условиях вибрации от собственно самого диска и всех
прочих вибраций. Как итог вполне можно попасть не на ту дорожку и придётся перепозиционировать
головки ещё раз.
Но зато можно успеть прочитать больше данных, если они идут последовательно в секторах
одной дорожки.
В общем, механический диск - штука крайне медлительная и прогресс CPU и оперативной
памяти (не имеющих механический частей и потому значительно более быстрых) в прошлом
тысячелетии потребовали вводить всевозможные ухищрения. В частности, операционные системы
начали кешировать операции чтения и записи данных в неиспользуемых в данный момент
выполняющимися программами областях оперативной памяти. И если с чтением всё просто
- точно такая же копия лежит в энергонезависимой памяти механических дисков - то с
кешированием записи как-то печальнее. Операционная система отвечает приложению "данные
записаны", а на самом деле они размещены в оперативной памяти и будут записаны когда-нибудь
чуть позже, может через несколько секунд. И это замечательно работает и ускоряет все
операции с дисков. Вот только при критическом сбое системы (например по питанию) данные
будут потеряны.
И чтобы дать приложениям возможность попросить систему именно записать какие-то данные
в энергонезависимую память и добавили вызов fsync, который синхронизирует кэш записи
с дисками.
Повторюсь - для механических дисков позиционировать головки операция очень медленная.
Поэтому если вы начнёте читать-писать с механическим диском с 1000 потоков - это будет
бесконечно долго. При том, ситуацию для вас всеми своими силами постараются сгладить
и планировщики ввода-вывода и кэширование файловых операций. Из-за позиционирования
головки механические диски могут давать неплохую производительность на последовательных
операциях, но производительность случайных операций у механики удручающая.
Но, к счастью, за последние лет 10 сильно подешевела flash-память и появились SSD
диски. Дисками их называют только по привычке, на самом деле никакой механики там уже
нет. И параллельная обработка запросов (пусть и за счёт обращений к разным кристаллам
памяти) и куда более внушительная производительность по метрике количества операций
в секунду (iops) - всё возможно. И, вероятно, со временем будут пересмотрены в сторону
упрощения и планировщики ввода-вывода (собственно blk_mq в ядре linux уже) и упрощены
другие нагромождения этих десятилетий когда для хранения данных использовалась медлительная
механика. У flash-памяти своих интересных фокусов тоже хватает (например, есть не 2
операции чтение и запись, а чтение, стирание, запись - запись возможна только в предварительно
очищенную страницу. Отсюда выросла необходимость в команде trim) - но это уже тема
отдельных изысканий.
Ответ 2 Например, если делаете контрольную точку вашей программы, т.е. хотите надежно записать
текущее состояние файла (его страниц из файлового кэша в ядре) на носитель.
Поскольку физические операции ввода/вывода переупорядочиваются для оптимизации доступа
(запросы от файловой системы ставятся в очередь к драйверу устройства) (можете прочесть
в упомянутой книге, см. лифт Линуса (видимо вы до этого места еще не дочитали)), то
в принципе, ограничительным фактором будет производительность диска (и конечно же,
стоимость сохранения контекста в системных вызовах все же не стоит совсем уж игнорировать).
#sql #oracle
Здравствуйте. Нужно упростить запрос но пока что не как не могу понять как это сделать.
Идея в том что бы все вложенные селекты переписать в джоины. ПОдскажит пожалуйста как
это сделать. Вот мой запрос.
select weight from myTableData
where port = (select port from myTableDict where Name = 'название') and
date = (
select max(date) from myTableData
where port = (select port from myTableDict where Name = 'название'));
Это пример моего запроса. Надеюсь всё расписал достаточно понятно. Если нет то пишите
объясню. Нужно сделать вместо селектов вложенных, джоины не могу пока что понять как
именно это сделать.
План запроса:
udp_port это port, w это myTableData, s это myTableDict.
Собстенно в таблице WEIGHER_DATA, 31 милион записей с небольшим. На ней есть 2 индекса.
На поле upd_port и на поле insert_date которое я подписал в примере как date. Стоимость
запроса почти под 56 тысяч как по мне многовато. С этой информацией можно как то упростить
и понизить стоимость запроса?
Ответы
Ответ 1 select max(weight) keep (dense_rank last order by M.port,M.date)
from myTableData M, myTableDict D
where D.Name='название' and M.port=D.port
Конструкция KEEP дает значение поля weight для последней (dense_rank last) записи
в порядке сортировки по дате. т.е. значение на максимальную дату. JOIN сокращен до
запятой и параметры из ON перенесены в where.
#mysql #sql
Нужно вывести item_id и price_in_rub. Price_in_rub – стоимость rub, считается как
price из таблицы items умноженная на курс валюты на максимальную дату выставления курса
из таблицы rates.
Выглядит все это примерно так:
Например: item_id=5 price = 20 EUR, в таблице rates максимальная дата выставления
курса евро – 13 января, на эту дату курс равнялся 3,0. Итого price_in_rub 20*3,0 = 60.
items
item_id |price | currency
1 |100 | USD
2 |10 | EUR
3 |20 | USD
4 |40 | USD
5 |20 | EUR
7 |400 | USD
rates
currency| date | rate
USD | 10.01.2017| 1,0
USD | 11.01.2017| 1,5
USD | 12.01.2017| 2,0
EUR | 13.01.2917| 3,0
EUR | 12.01.2017| 2,5
Ответы
Ответ 1 Решение с корелированым подзапросом:
SELECT
itm.item_id
,(itm.price * cur.rate) price_in_rub
FROM items itm
CROSS APPLY
(
SELECT TOP 1 rate
FROM rates
WHERE itm.currency = rates.currency
ORDER BY date desc
) cur
Ответ 2 Вот такой вариант по быстрее будет:
SELECT it.item_id, it.price*r.rate AS price_in_rub
FROM dbo.items AS it
JOIN dbo.rates AS r ON it.currency = r.currency
WHERE r.date = (SELECT MAX(date) FROM dbo.rates AS r2 WHERE r.currency = r2.currency)
#cpp #c #указатели
Почему появляются проблемы подобного рода ?
Ответы
Ответ 1 char* f()
{
char s[100];
// страшное вычисление s
return s;
}
Представили? вызываем char * s = f();. Нормально? вроде бы да.
Но когда мы начнем использовать этот указатель - тот char s[100]; из функции давно
может быть перезаписан чем-то другим (эта память выделяется в стеке только на время
работы функции). И мы получаем висячий указатель - т.е. он есть и даже куда-то указывает...
Только там может быть что угодно.
Или -
s = malloc(...);
....
free(s);
Значение s остается - free его не меняет, но указывает оно на память, которая освобождена,
может быть выделена заново, перезаписана... или, например, еще раз удалена.
Так понятнее?
#cpp #cpp11
Почему оно работает? Слышал об предварительном объявлении, но это явно другой случай.
Или в чистом виде UB?
Сам код на IdeOne
#include
using namespace std;
const int x = 5;
int main(){
int x[x];
cout << "OK!" << endl;
return 0;
}
Ответы
Ответ 1 Нет, это не UB. Согласно стандарту, раздел 6.3.2, клауза 2 упоминает в точности ваш
пример:
const int i = 2;
{ int i[i]; }
В нём определяется массив из двух целых чисел внутри блока.
Полная цитата из стандарта (перевод мой):
Точка декларации имени находится непосредственно за её полным декларатором (...)
и перед инициализатором (если он есть), за исключением замечаний ниже.
[ Пример:
unsigned char x = 12;
{ unsigned char x = x; }
Здесь второй x инициализируется своим собственным (неопределённым) значением. — конец
примера ]
[ Замечание: Имя из внешней области действует вплоть до точки декларации имени, которое
его перекрывает. [ Пример:
const int i = 2;
{ int i[i]; }
определяет внутриблоковый массив из двух целых. — конец примера ] — конец замечания ]
#javascript #html #jquery #html5
На сей раз возник вопрос к var. Как заставить переменную перезаписывать своё значение
при каждом новом вызове функции?
Весь код функции прилагается.
function tablecell(){
var st = $(this).attr('id');
console.log(st);
if($(this).is('.disabled')){
}
else{
$('.questionBg').css({'display':'flex'});
function answer(){
if ($(this).is('#true')){
$(this).css({'background':'#83c849'}).css({'color':'#fff'});
$('.answer').addClass('disabled');
$('.disabled').off('click', answer);
$('.teamSelection').css({'display':'flex'});
$('.selectTeam').click(function(){
$(close);
alert(st);
$("#"+st).addClass('disabled');
if($(this).is('.selectTeam1')){
$("#"+st).children('.question').css({'display':'none'});
$("#"+st).children('.team1').css({'display':'block'});
}
else{
$("#"+st).children('.question').css({'display':'none'});
$("#"+st).children('.team2').css({'display':'block'});
}
});
}
else{
$(this).css({'background':'#e03a3a'}).css({'color':'#fff'});
$('.answer').addClass('disabled');
$('.disabled').off('click', answer);
setTimeout(close, 1000);
}
}
}
$('.answer').click(answer);
};
Вызов производится извне:
$(document).ready(function(){
$('.tablecell').click(tablecell);
});
У меня ощущение, что функция банально не завершается, но новое значение в консоль
при повторном вызове выводится.
Однако, alert с каждым разом повторно выводит предыдущие значения. Что делать - не
пойму. Массивом прописать?
Какого цвета этот блок?
Варианты ответа:
Синий
Красный
Серый
Белый
Ответы
Ответ 1 Что делать
Не назначать обработчики событий внутри других обработчиков событий.
Каждый раз, когда выполняется функция tablecell, Вы добавляете новый обработчик события
click всем элементам с классом "answer". По щелчку на такой элемент выполняются все
накопившиеся обработчики.
(function(){
var st;
function answer(){
...
}
function tablecell(){
st = $(this).attr('id');
console.log(st);
if($(this).is('.disabled')){
} else {
$('.questionBg').css({'display':'flex'});
}
}
$(document).on('click', '.tablecell', tablecell);
$(document).on('click', '.answer', answer);
})();
#c_sharp #wpf
Иногда кнопка после выполнения команды не становится активной.
Помогает клик по форме. Скажете пожалуйста в чем может быть проблема?
XAML:
C#:
private readonly RaiseCommand doneCommand;
private readonly BackgroundWorker worker;
private object _currentUserState;
private int _currentProgress;
public RaiseCommand DoneCommand
{
get { return doneCommand; }
}
public MainWindowViewModel()
{
doneCommand = new RaiseCommand(o => worker.RunWorkerAsync(), o => !worker.IsBusy);
worker = new BackgroundWorker();
worker.DoWork += DoDoneCommand;
worker.ProgressChanged += ProgressChanged;
worker.RunWorkerCompleted += RunWorkerCompleted;
worker.WorkerReportsProgress = true;
}
private void DoDoneCommand(object sender, DoWorkEventArgs e)
{
MessageBox.Show("test");
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
CurrentUserState = e.UserState;
CurrentProgress = e.ProgressPercentage;
}
private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
Класс RaiseCommand:
public class RaiseCommand : ICommand
{
readonly Action _action;
readonly Func _canExecute;
public RaiseCommand(Action execute) : this(execute, null) { }
public RaiseCommand(Action execute, Func canExecute)
{
_action = execute ?? throw new ArgumentNullException("execute");
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_action(parameter);
}
}
Ответы
Ответ 1 Без клика по окну не обновляется состояние кнопки и не вызывается CanExecute, соответственно,
кнопка остается неактивной.
Обновленный ответ: Для явного обновления интерфейса вручную можете попробовать вызвать
CommandManager.InvalidateRequerySuggested по завершении потока:
private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
CommandManager.InvalidateRequerySuggested();
}
Из документации:
The CommandManager only pays attention to certain conditions in determining when
the command target has changed, such as change in keyboard focus. In situations where
the CommandManager does not sufficiently determine a change in conditions that cause
a command to not be able to execute, InvalidateRequerySuggested can be called to force
the CommandManager to raise the RequerySuggested event.
Ответ до обновления: Можно попробовать явно вызвать CanExecuteChanged после завершения
BackgroundWorker. Для этого в комманду добавляем свое событие и метод его вызова:
//объявляем событие
private event EventHandler InternalCanExecuteChanged;
//привязываем его к CanExecuteChanged
public event EventHandler CanExecuteChanged
{
add
{
InternalCanExecuteChanged += value;
CommandManager.RequerySuggested += value;
}
remove
{
InternalCanExecuteChanged -= value;
CommandManager.RequerySuggested -= value;
}
}
//метод для вызова
public void RaiseCanExecuteChanged()
{
var handler = InternalCanExecuteChanged;
if (handler != null)
handler(this, EventArgs.Empty);
}
и обращаемся к методу после завершения потока:
private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
doneCommand.RaiseCanExecuteChanged();
}
Ответ 2 Позволю себе написать ответ, хотя он только косвенно относится к озвученному вопросу.
Если вы хотите блокировать активность кнопки до тех пор пока некоторая длительная
операция будет завершена, то возможно правильным решением будет воспользоваться асинхронными
командами вместо того, чтобы применять немного устаревший BackgroundWorker
По идее асинхронные версии команд должны предоставляться основными библиотеками упрощающими
разработку WPF проекты.
Если по каким-то причинам вы не хотите их подключать, то можно найти реализации AsyncCommand
в интернете.
Например, отличная статья
Async Programming : Patterns for Asynchronous MVVM Applications: Commands
Чтобы ответ был более полным приведу пример тривиального таймера обратного отсчета,
когда мы не можем (не должны) запускать новый до истечения предыдущего.
Разметка
и контекст
let source = Bind.createSource()
let step = 1000
let startInt = 10
let Count = Mutable.create startInt
let start _ =
async {
while Count.Value > 0 do
do! Async.Sleep step
Mutable.step (fun x -> x - 1) Count
return startInt
}
Bind.Explicit.oneWay source "Count" Count
Bind.Explicit.createCommand "Start" source
|> Observable.mapAsyncTracked start source.IdleTracker
|> Observable.subscribe (Mutable.set Count)
|> source.AddDisposable
При написании использована библиотека Gjallarhorn.Bindable.Wpf
#html #css
Здравствуйте, есть такая задача. Несколько блоков на сайте расположены друг под другом,
при наведении на первый, его высота увеличивается и нижний сьезжает вниз соотвтественно.
Подскажите возможно ли сделать так? упрощенная схема как это работает сейчас внизу
в коде. Возможно ли это сделать не оборачивая эти два блока в дополнительный?
div{
width:200px;
height:100px;
}
.red{
background-color:red;
}
.green{
background-color:green;
}
.red:hover{
height:150px;
}
1
2
Ответы
Ответ 1 вот так можно но это грубо, хотя зависит от ситуации, что именно тебе надо и как...
div {
position: absolute;
width: 200px;
height: 100px;
}
.red {
background-color: red;
}
.green {
top: 100px;
background-color: green;
}
.red:hover {
height: 150px;
z-index: 11;
}
1
2
#java
Есть такой кусок кода
Integer page;
if (request.queryParams("size") != null) {
page = Integer.parseInt(Optional.of(request.queryParams("size")).orElse(null));
} else {
page = null;
}
Integer limit;
if (request.queryParams("limit") != null) {
limit = Integer.parseInt(Optional.of(request.queryParams("limit")).orElse(null));
} else {
limit = null;
}
Как его изменить, что бы убрать эти проверки на null, с помощью Optional?
Если пишу так, то не работает, все равно получается NullPointerException, если нет
"size" или "limit"
Integer page = Integer.parseInt(Optional.of(request.queryParams("size")).orElse(null));
Integer limit = Integer.parseInt(Optional.of(request.queryParams("limit")).orElse(null));
Ответы
Ответ 1 page = Optinal
.ofNullable(request.queryParams("size"))
.filter(v -> v.matches("\\d+"))
.map(Integer::parseInt)
.orElse(1);
#c_sharp #юнит_тесты #moq
Не могу разобраться для чего используется Mock.Verifiable(), если я правильно понимаю,
такой код:
var mockContainer = new Mock(MockBehavior.Strict, StorageUri);
mockContainer.Setup(c => c.GetBlockBlobReference(It.IsAny()))
.Returns(mockBlobItem.Object);
// ...
mockContainer.Verify(c => c.GetBlockBlobReference(It.IsAny()), Times.AtLeastOnce);
Будет эквивалентен такому:
var mockContainer = new Mock(MockBehavior.Strict, StorageUri);
mockContainer.Setup(c => c.GetBlockBlobReference(It.IsAny()))
.Returns(mockBlobItem.Object)
.Verifiable();
// ...
mockContainer.Verify();
Есть ещё третий вариант:
var mockContainer = new Mock(MockBehavior.Strict, StorageUri);
mockContainer.Setup(c => c.GetBlockBlobReference(It.IsAny()))
.Returns(mockBlobItem.Object);
// ...
mockContainer.Verify();
Изучил множество примеров, так вот там используются, как правило, второй или третий
варианты. А ещё есть .VerifyAll().
Как правильно и почему?
Какие есть особенности и подводные камни?
Как эти варианты зявисят от моделей поведения Strict и Loose?
Не смог найти документацию к Moq (кроме вот этой неполноценной), она вообще есть?
Ответы
Ответ 1 Да Вы всё верно поняли.
Насколько можно судить из статьи этот метод может быть использован для проверки вызова
ранее вызова метода определённого в Setup.
var thing = new Thing() { Id = 1 };
var mockMapper = new Mock();
mockMapper.Setup(p => p.Save(thing)).Verifiable();
// do stuff
mockMapper.Verify();
Кроме того согласно англоязычного ответа желательно не использовать этот подход т.к.
он явно противоречит паттерну AAA. Противоречие заключается в том, что подготовка данных
для тестирования (Arrange) и описание того, что должно быть проверено (Assert) происходит
в методе Setup.
Сами же мейнтейнеры проекта озвучивают ещё рад случаев почему не стоит продолжать
развивать такое АПИ
Тем не менее этот подход может быть оправдан к примеру необходимостью избежать дублитрования
кода.
Единственный случай, когда такой подход нельзя будет использовать это при необходимости
проверить количество вызовов. В этом случае Вы можете использовать только метод Verify
с полным описание ожидаемого вызова:
mock.Verify(c => c.Method(It.Is(x => x == "x")), Times.Once);
По поводу использования Verify без параметров. Он будет проверять только методы которые
Вы в сетапе отметили при помощи метода Verifiable:
var mockContainer = new Mock(MockBehavior.Strict, StorageUri);
mockContainer.Setup(c => c.GetBlockBlobReference(It.IsAny()))
.Returns(mockBlobItem.Object)
.Verifiable();
// ...
mockContainer.Verify();
Если же вы хотите проверить был ли вызван метод который не был отмечем как Verifiable,
можно использовать метод VerifyAll:
var mockContainer = new Mock(MockBehavior.Strict, StorageUri);
mockContainer.Setup(c => c.GetBlockBlobReference(It.IsAny()))
.Returns(mockBlobItem.Object);
// ...
// Verify - не будет проверять в этом случае
// т.к. Вы не получите ошибку даже если метод не был вызван ни разу
// для такого случая можно сделать так
mockContainer.VerifyAll();
Но лично я бы не использовал VerifyAll хотя-бы потому, что он ну уж совсем не очевиден.
Разработка ведётся на гитхабе и кроме детальной документации на которую вы сослались
есть быстрый старт и примеры использования.
#c_sharp #многопоточность
Является ли Dictionary потокобезопасным для чтения и перебора
значений?
То есть записи в этот Dictionary не будет (инициализируется только при запуске проекта),
и хочу понять можно ли его использовать в контексте singleton сервиса в ASP.NET Core 2.0?
Ответы
Ответ 1 https://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx
Thread Safety
A Dictionary can support multiple readers concurrently,
as long as the collection is not modified.
то есть
Потокобезопасность
... поддерживает несколько одновременных операций чтения, постольку
поскольку данные не изменяются.
Ответ 2 Смотрите, сам по себе словарь является потокобезопасным для случая, когда у вас есть
лишь операции чтения из разных потоков. Однако для случая, когда вам ещё нужна инициализация,
необходимо учитывать возможные «гонки» между инициализирующим потоком, и потоком, который
читает уже инициализированный словарь.
Рассмотрим такой код:
var dict = Dictionary();
dict[k1] = v1; // инициализация
GlobalAccessibleDict = dict; // публикация
Я проштудировал спецификацию и не нашёл пункта, который запрещал бы компилятору переставить
инициализацию и публикацию, ведь с точки зрения публикующего потока от перестановки
этих присваиваний смысл кода не меняется. Таким образом, с точки зрения другого, читающего
потока инициализация может произойти слишком поздно. Итак, судя по всему, с точки зрения
языка этот паттерн неправильный, и может привести к чтению другим потоком недоинициализированного
словаря. Для того, чтобы быть уверенныйм, необходимо использовать lock (или, возможно
публикацию через volatile-поле).
С другой стороны, с точки зрения имплементации в Microsoft .NET, статья Joe Duffy
CLR 2.0 memory model утверждает, что в имплементации .NET 2.0
Rule 2: All stores have release semantics, i.e. no load or store may move after one.
то есть, перестановки записей в переменные недопустимы. Если я правильно понял этот
текст, это означает, что гонка, описанная мной, невозможна, и инициализация закончится
строго до публикации. Поэтому с хорошей долей вероятности в текущей реализации (а модель
памяти .NET 4.0 вроде бы не слабее) в вашем подходе всё хорошо. (Я не нашёл, однако,
ничего про порядок актуализации данных в других потоках, так что тонкости остаются.)
#windows #virtualbox #hyper_v
Не получается запустить виртуалку в virtualbox.
- В UEFI параметр VT-d включён.
- Служба Hyper-V работает.
- Процессор виртуализацию поддерживает.
- Windows 10.
Если выполнить команду systeminfo: Требования Hyper-V: Обнаружена низкоуровневая
оболочка. Функции, необходимые для Hyper-V, отображены не будут.
Если поставить виртуалку через Vagrant, при запуске виртуалки машина падает в BSOD.
Ответы
Ответ 1 Нашёл решение проблемы. Как я понял для безопасности винда как бы сама запускается
в вируталке, поэтому выдаёт такое сообщение. Эта функция называется Credential Guard.
Для того чтобы отключить эту фишку нужно:
Программы и компоненты -> Включение или отключение компонентов Windows -> Hyper-V
-> Платформа Hyper-V -> Низкоуровневая оболочка Hyper-V (убрать галку)
#java #android
Доброго времени суток. Сразу же извиняюсь за возможную кривизну вопроса.
Можно ли программно проверить версию приложения в Play Market, чтобы при появлении
обновления, пользователи старой версии, через само приложение узнали бы о появления
обновления?
Спасибо.
Ответы
Ответ 1 Вы как разработчик меняете версию в своем приложении и заливаете на Маркет. Маркет
автоматом уведомляет старую версию, в данном случае, пользователя (устройство) со старой
версией о наличии обновления.
Ответ 2 Есть сторонняя библиотека AppUpdater: https://github.com/javiersantos/AppUpdater
AppUpdater проверяет наличие обновлений на Google Play, GitHub, Amazon, F-Droid или
вашем собственном сервере. Библиотека сообщает о наличии обновлений в вашем приложении
при помощи диалога, Snackbar или уведомления.
#c_sharp #xml #svg #inkscape
Имеется xml-документ с несколькими элементами rect и line.
Возможно ли получить доступ к редактированию любого из этих элементов при открытии
соответствующего svg-файла в графических редакторах, "знающих" SVG?
Ответы
Ответ 1 Вы просто попробуйте скачать Inkscape с официального сайта
И открыть файл, затем редактируйте его по вашим потребностям.
Уроков по Inscape достаточно много, да и без них интуитивно понятно,
что делать, тем более интерфейс редактора на русском.
Далее сохраняете файл в нужном вам формате. В файле очень много служебной информации,
его можно использовать и так, но лучше оптимизировать.
Для оптимизации есть очень хороший редактор онлайн SVG-Editor
Всё бесплатно, пользуйтесь.
Upd по комментариям автора вопроса
Пример анимации простейших фигур SVG (Рисование спирали с одновременным движением
шарика)
Mouseover
Пояснения как это сделать
Учитесь на примерах, правьте их, пишите свои, самые элементарные
#oracle #rman
Как развернуть backup, сделанный с помощью RMAN на резервном сервере?
Так же интересует, не важно ли для переноса, какая ОС системы?
На работающем сервере БД был запущен Rman и выполненны следующие команды:
connect target;
shutdown immediate;
startup mount;
backup database;
alter database open;
Затем файлы бекапа были скопированны на ПК где планируется развернуть резервную БД
путь к папке E:\backup. На резервном ПК был запущен Rman со следующими командами:
connect target;
shutdown immediate;
startup mount;
catalog start with 'E:\backup\';
Затем соглашаюсь добавить данные бекапы написав yes. Затем получаю ошибку
File Name: путь и имя файла
RMAN-07518: Reson: Foreign
database file DBID: 4099333308
Database Name: ORCL
Затем где-то читал, что можно написать set DBID 4099333308 и повторить заново, но
ничего не вышло. БД даже не поднялась, указывая на то, что неверный DBID. Поэтому DBID
я вернул какой был. Как решить проблему?
Ответы
Ответ 1 Возможно проблема из за того что вы не восстановили SPFILE и CONTROLFILE.
Стартуем БД без монтирования spfile:
startup nomount;
Восстанавливаем spfile:
restore spfile from ’путь к файлу в бекапе *.CTF’;
Останавливаем
shutdown immediate;
Стартуем в режиме nomount,и восстанавливаем контрольный файл:
restore controlfile from ’путь к файлу в бекапе *.CTF’;
Стартуем в режиме mount
startup mount.
catalog start with ‘полный путь к папке бекапа’;
Соглашаемся: Y
run
{
restore database;
recover database;
}
После восстановления появится ошибка, SCN не сходится. Сбрасываем SCN и стартуем
alter database open resetlogs;
Если исходный сервер(Oracle) был 32-битный а новый 64 то необходимо выполнить в sqlplus:
startup upgrade
@$Oracle_Home\rdbms\admin\utlip.sql
@$Oracle_Home\rdbms\admin\catupgrd.sql
@$Oracle_Home\rdbms\admin\utlrp.sql
shutdown immediate
startup
#c_sharp #encoding #net_core
Всем привет. Столкнулся с проблемой: нужно отправлять сообщение на почтовый ящик
в кодировке koi8-u(21866). Использую пакет System.Text.Encoding.CodePages:
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
MailAddress fr = new MailAddress("***@**.com", "Name");
MailAddress to = new MailAddress("***@**.com");
MailMessage m = new MailMessage(fr, to)
{
Body = "test",
BodyEncoding = Encoding.GetEncoding("koi8-u")
};
await smtp.SendMailAsync(m);
Но при отправке получаю: No data is available for encoding 21866. For information
on defining a custom encoding, see the documentation for the Encoding.RegisterProvider
method.
В обычном .NET Framework-е все отлично отправляется, в .NET Core увы. Как можно решить это?
P.S: такая же ситуация и для windows-1252 и прочих.
Ответы
Ответ 1 Просто подключите в проект NuGet-пакет с расширенными кодировками:
System.Text.Encoding.CodePages
И перед использованием зарегистрируйте их:
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Должно помочь.
#c_sharp #linq
Есть метод, возвращающий последовательность, состоящую из пар соседних элементов.
Например, по последовательности {1,2,3} метод должен вернуть две пары: (1,2) и (2,3).
Решение, которое сразу пришло в голову:
return items
.Take(items.Count() - 1)
.Zip(items.Skip(1), Tuple.Create);
Но в данном случае IEnumerable перечисляется больше одного раза. Как можно решить
задачу без нескольких перечислений (сохранив метод ленивым)?
Ответы
Ответ 1 Например, так. Объявим метод расширения, который выдаёт последовательные пары:
public static class EnumerableExtensions
{
public static IEnumerable Pairwise(
this IEnumerable sequence, Func selector)
{
using (var it = sequence.GetEnumerator())
{
if (!it.MoveNext())
yield break;
T prev = it.Current;
while (it.MoveNext())
yield return selector(prev, prev = it.Current);
}
}
}
И пользуемся:
return items.Pairwise(Tuple.Create);
Ответ 2 Как насчет отдельной функции?
public IEnumerable> GetItems(IEnumerable source)
{
var prev = default(T);
var firstVisited = false;
foreach(var item in source)
{
if (firstVisited)
{
yield return Tuple.Create(prev, item);
}
else
{
firstVisited = true;
}
prev = item;
}
}
#python #pandas #dataframe
У меня есть датафрейм, состоящий из двух столбцов. в первос записаны емейлы пользователей,а
во втором - страны проживания. Мне нужно выбрать из первого те значения, которе содержат
gmail.com или hotmail.com. А потом построить график "отношение количества gmail.com
и hotmail.com в соответствии со страной."
В чем ошибка?
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
df = pd.read_csv("/home/ann/df(1).csv", sep=';')
gmail_list = []
hotmail_list = []
for i in df[['email', 'country_code']]:
if "@gmail.com" in i:
gmail_list.append(df.loc[:,'country_code'])
elif "@hotmail.com" in i:
hotmail_list.append(country_code)
график
Ответы
Ответ 1 В Pandas данную задачу можно решить однострочным (one-liner) выражением:
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
matplotlib.style.use('ggplot')
df = pd.read_csv(r'D:\download\df(1).csv', sep=';')
(df.assign(domain=df['email'].str.extract(r'@(.*)', expand=False))
.query("domain in ['gmail.com','hotmail.com']")
.groupby(['country_code','domain'])
.count()['email']
.unstack('domain', fill_value=0)
.plot.bar(rot=0, stacked=True))
plt.show()
Результат:
В процентах:
(df.assign(domain=df['email'].str.extract(r'@(.*)', expand=False)) # extract domain
from email
.query("domain in ['gmail.com','hotmail.com']") # filter domains
.groupby('country_code')['domain'] # group by `country_code`
.value_counts(normalize=True) # and count unique values
per group (normalize: relative frequency)
.mul(100) # convert factor to percentage
.unstack('domain', fill_value=0) # pivot: transform long
to wide
.plot.bar(rot=0, stacked=True, figsize=(12,8)))
)
Результат:
Как это работает?
Сначала надо вычленить домен из email:
In [113]: df.assign(domain=df['email'].str.extract(r'@(.*)', expand=False))
Out[113]:
email country_code domain
0 12345kinglobito94@hotmail.com RU hotmail.com
1 12345arturdyikan6211@gmail.com RU gmail.com
2 12345leonardosebastianld.20@gmail.com PE gmail.com
3 12345k23156876vs@hotmail.com RU hotmail.com
4 12345jhuillcag@hotmail.com PE hotmail.com
.. ... ... ...
995 nilton223009@hotmail.com PE hotmail.com
996 xasbkar@gmail.com RU gmail.com
997 kl@gmail.com RU gmail.com
998 emerson-carauna@hotmail.com BR hotmail.com
999 shamkhalaevamir@gmail.com RU gmail.com
[1000 rows x 3 columns]
потом отфильтровать, чтобы остались только gmail.com и hotmail.com:
In [114]: (df.assign(domain=df['email'].str.extract(r'@(.*)', expand=False))
...: .query("domain in ['gmail.com','hotmail.com']"))
...:
Out[114]:
email country_code domain
0 12345kinglobito94@hotmail.com RU hotmail.com
1 12345arturdyikan6211@gmail.com RU gmail.com
2 12345leonardosebastianld.20@gmail.com PE gmail.com
3 12345k23156876vs@hotmail.com RU hotmail.com
4 12345jhuillcag@hotmail.com PE hotmail.com
.. ... ... ...
995 nilton223009@hotmail.com PE hotmail.com
996 xasbkar@gmail.com RU gmail.com
997 kl@gmail.com RU gmail.com
998 emerson-carauna@hotmail.com BR hotmail.com
999 shamkhalaevamir@gmail.com RU gmail.com
[954 rows x 3 columns]
считаем количество различных доменов для каждой страны:
In [115]: (df.assign(domain=df['email'].str.extract(r'@(.*)', expand=False))
...: .query("domain in ['gmail.com','hotmail.com']")
...: .groupby('country_code')['domain']
...: .value_counts(normalize=True)
...: )
Out[115]:
country_code domain
AR hotmail.com 0.750000
gmail.com 0.250000
BR hotmail.com 0.609375
gmail.com 0.390625
PE hotmail.com 0.702564
gmail.com 0.297436
RU gmail.com 0.956298
hotmail.com 0.043702
US gmail.com 0.900000
hotmail.com 0.100000
Name: domain, dtype: float64
делаем PIVOT:
In [116]: (df.assign(domain=df['email'].str.extract(r'@(.*)', expand=False))
...: .query("domain in ['gmail.com','hotmail.com']")
...: .groupby('country_code')['domain']
...: .value_counts(normalize=True)
...: .mul(100)
...: .unstack('domain', fill_value=0)
...: )
Out[116]:
domain gmail.com hotmail.com
country_code
AR 25.00000 75.00000
BR 39.06250 60.93750
PE 29.74359 70.25641
RU 95.62982 4.37018
US 90.00000 10.00000
рисуем график...
#c #указатели
Изучаю указатели на указатели в Си и возникли небольшие "непонятки".
int **pp, *p, A = 10, B = 20;
p = &A, pp = &p; /* сейчас *p = **pp = 10 */
*pp = &B; /* теперь *p = **pp = 20 */
Кто-нибудь может мне объяснить, почему можно делать так, как мы сделали в строчке
3? Я экспериментально определил, что *pp и p лежат по одному адресу (но для вас это
вряд ли новость), но почему так происходит я не совсем понимаю.
Ответы
Ответ 1 int **pp, *p, A = 10, B = 20;
p = &A
В p записан адрес переменной A.
pp = &p;
В pp записан адрес переменной p. Значит, *pp - это по сути переменная p, в которой
хранится адрес A. Ну, а **pp - это то же, что и *p, т.е. значение по адресу, хранящемуся
в p - а там хранится адрес A. Значит, это значение A, т.е. 10.
*pp = &B;
Вспомним, что в pp хранится адрес переменной p, так что *pp по сути получается тем
же, что и p. Т.е. запись в *pp сейчас - когда в pp хранится адрес p - то же самое,
что запись в переменную p. А записываем мы туда адрес переменной B.
А дальше применимы все те же рассуждения, что были сделаны выше, когда в p хранился
адрес переменной A...
#java
Давайте представим, что есть некий метод, который принимает скажем 3 параметра.
public void something(final String id, final String name, final Entity entity){
//...
}
В данном случае все параметры помечены как final. Т.е. я точно знаю, что не буду
их изменять, а только буду пользоваться их значениями.
Какие + и - описанного выше. Стоит ли писать слово 'final' в параметрах метода? Имеет
ли это какой-либо смысл в плане оптимизации?
Ответы
Ответ 1 Вот такой класс
public class Final {
private final String second;
private String first;
public Final(String first, final String second) {
this.first = first;
this.second = second;
}
}
Компилируется в вот такой байткод
// class version 52.0 (52)
// access flags 0x21
public class Final {
// compiled from: Final.java
// access flags 0x12
private final Ljava/lang/String; second
// access flags 0x2
private Ljava/lang/String; first
// access flags 0x1
public (Ljava/lang/String;Ljava/lang/String;)V
L0
LINENUMBER 5 L0
ALOAD 0
INVOKESPECIAL java/lang/Object. ()V
L1
LINENUMBER 6 L1
ALOAD 0
ALOAD 1
PUTFIELD Final.first : Ljava/lang/String;
L2
LINENUMBER 7 L2
ALOAD 0
ALOAD 2
PUTFIELD Final.second : Ljava/lang/String;
L3
LINENUMBER 8 L3
RETURN
L4
LOCALVARIABLE this LFinal; L0 L4 0
LOCALVARIABLE first Ljava/lang/String; L0 L4 1
LOCALVARIABLE second Ljava/lang/String; L0 L4 2
MAXSTACK = 2
MAXLOCALS = 3
}
Как видно, в сгенерированном байткоде, у final String second исчез модификатор final
- Ljava/lang/String;
Т.е. в случае использования final как параметра метода или конструктора, ограничения
накладываются только на этап компиляции (т.е. компилятор выдаст ошибку, если вы будете
изменять значение final переменной), а в байткоде эти модификаторы будут банально отброшены,
так как особого смысла в них уже не будет.
#javascript #html
Как вычислить (получить) позицию html елемента. offsetTop и offsetLeft даёт относительное
значение (не всегда отчёт от точки [x=0,y=0] начала координат). Гугл даёт "недоделанный"
вариант http://javascript.ru/ui/offset.
Не "как динамический во время scroll определить текущее местоположение элемента по
отношению к родителю", а как получить абсолютные координаты относительно левого верхнего
угла содержимого страницы.
Второй вопрос "определить текущее местоположение элемента по отношению к родителю"
ещё раз повторяю, абсолютные координаты относительно левого верхнего угла содержимого
страницы.
Нужно для "подвешивания" элементов к текущей верстке (что бы вывести на/возле определённого
элемента подсказку, сообщение, рекламу и т.п.) например так:
document.getElementById("act_holder").style.position= "absolute";
document.getElementById("act_holder").style.display = "block";
document.getElementById("act_holder").style.top =
(getOffset(document.getElementById("act_hlp")).top - 75 ) + "px";
document.getElementById("act_holder").innerHTML = "элемент занят";
при использовании absolute нужны координаты относительно левого верхнего угла.
Ответы
Ответ 1 Вот код с javascript.ru собраный до кучи.
function getOffset(elem) {
if (elem.getBoundingClientRect) {
var box = elem.getBoundingClientRect();
var body = document.body;
var docElem = document.documentElement;
var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
var clientTop = docElem.clientTop || body.clientTop || 0;
var clientLeft = docElem.clientLeft || body.clientLeft || 0;
return { top: Math.round(box.top + scrollTop - clientTop), left: Math.round(box.left
+ scrollLeft - clientLeft) }
} else {
var top=0, left=0
while(elem) {
top = top + parseFloat(elem.offsetTop);
left = left + parseFloat(elem.offsetLeft);
elem = elem.offsetParent ;
}
return {top: top, left: left};
}
}
Немного комментариев:
ф-ция getBoundingClientRect вызвала спор, mozilla цитата
Возвращаемое значение getBoundingClientRect — это объект TextRectangle, содержащий
свойства
только для чтения left, top, right и bottom, описывающие бокс с
границами в пиксельном измерении. Значения top и left даются
относительно верхнего левого угла порта просмотра.
т.е. уже с учётом скролла и отступов документа, которые приходится вычитать если
нужны координаты относительно начала системы координат листа (левый верхний угол документа).
Даная функция getBoundingClientRect даст верный результат, если выполняется два условия:
1) позиция скроллинга ноль (на старте часто так), 2) если у документа (body) отступы
не заданы, или заданы в ноль. Так как эти условия не всегда соблюдены - приходится
использывать более сложные решения.
От себя добавлю, что если используется система отчёта position=fixed то getBoundingClientRect
выдаст координаты которые подойдут к этой системе отчёта, но fixed редко используется,
поскольку при изменении позиции скрола - позиция на экране сохраняется и елемент будет
"плавать". А для absolute и static прийдётся делать пересчёт коодинат. Система relative
- просто относительные координаты, в отдельных случаях её можно использовать.
Ответ 2 Кликни на любой элемент получишь данные
Объясни, какие ты еще хочешь получить координаты абсолютные??? Вполне вероятно,
что пойму...
Смотреть лучше на весь экран
var wrapper = document.getElementById('wrapper');
var infomBlock = document.getElementById('infomBlock');
var blocks = document.getElementsByClassName('blocks');
function getСoordinates(elem) {
return coord = [
'это абсолютное значени нижней границы элемента от окна просмотра - bottom '
+ elem.getBoundingClientRect().bottom,
' это абсолютное значени верхней границы элемента от окна просмотра - top
' + elem.getBoundingClientRect().top,
' это абсолютное значени левой границы элемента от окна просмотра - left
' + elem.getBoundingClientRect().left,
' right это абсолютное значени правой границы элемента от окна просмотра
- ' + elem.getBoundingClientRect().right,
' height - это абсолютное значени высоты элемента ' + elem.getBoundingClientRect().height,
' width - это абсолютное значени ширины элемента ' + elem.getBoundingClientRect().width,
' x - это абсолютное значени верхнего левого угла элемента по координате
х' + elem.getBoundingClientRect().x,
' y - это абсолютное значени верхнего левого угла элемента по координате
y ' + elem.getBoundingClientRect().y,
];
console.log(...coord)
}
for (var i = 0; i < blocks.length; i++) {
blocks[i].addEventListener('click', function() {
getСoordinates(this);
infomBlock.innerHTML = coord;
})
}
* {
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 100%;
background: #272727;
}
#wrapper {
color: white;
width: 100%;
height: 100%;
}
#infomBlock.blocks {
display: block;
margin: 0;
background: rgba(200, 200, 200, .5);
width: 100%;
height: 200px;
color: white;
}
.blocks {
cursor: pointer;
display: inline-block;
margin: 50px 20px;
color: white;
width: 150px;
height: 150px;
background: orange;
}
.blocks:nth-child(even) {
margin: 150px 10px;
}
Ответ 3 Если используется jQuery - то всё просто:
$('#element').offset();//вернёт координаты в формате {top: float, left: float}
Будет работать всегда, кроме fixed-элементов. Это позиция от края документа - позиция
внутри страницы.