Страницы

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

четверг, 7 марта 2019 г.

Как определить текущее местоположение пользователя и что лучше использовать?

Есть интернациональный проект. При совершении пользователем определенных действий, необходимо получать данные о его местоположении (страна, город, улица(если возможно)), и после уже отсылаем эти данные на наш сервер. Я видел примеры от гугл и яндекс карт, там можно получить координаты. Я все же более склонен к использованию гугла.
Есть ли пример получения этих данных при этом сделав как можно меньше запросов?
P.S. При этом мне не нужно что-либо отрисовывать на карте и рисовать саму карту


Ответ

Силами HTML5 — navigator.geolocation.getCurrentPosition(). Браузер спрашивает у пользователя разрешение и в случае согласия отдает ОЧЕНЬ (в большинстве случаев) точные данные в виде широты и долготы. Потом это можно скормить https://developers.google.com/maps/documentation/geocoding/intro без карты. upd 2018: данный способ работает для https-сайтов Определять по IP. Есть бесплатная (но не самая полная) база — https://dev.maxmind.com/ru/geolite2/ Вот есть библиотека под нее — https://github.com/maxmind/GeoIP2-php В этом случае данные доступны сразу, но они не точные (Страна, город).

Динамическое добавление методов к объекту в Python 3

Допустим у меня есть класс
class A: x, y = 1, 2
и объект для этого класса
a = A()
Как добавить к a новый метод?
Если сделать так
a.f = lambda self: self.x + self.y print(a.f())
то получаю ошибку
Traceback (most recent call last): File "python", line 8, in TypeError: () missing 1 required positional argument: 'self'
А если так
a.f = lambda: "body"
то внутри лямбда функции у меня нет доступа к объекту.


Ответ

https://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object-instance
import types
class A: x, y = 1, 2
a = A() a.f = types.MethodType(lambda self: self.x + self.y, a) a.f() # --> 3
Разница в следующем:
a.g = lambda self: self.x + self.y a.f # --> of <__main__.A object at 0x7f4de50d5978>> a.g # --> at 0x7f4de51babf8>
Но:
>>> A.h = lambda self: self.x + self.y >>> a.h() 3

Косвенное присвоение значений переменным

Скрипт:
#!/bin/bash test1="" test2="" t_array=( "test1" "test2" )
index=$((${#t_array[@]}-1)) while [ $index -gt -1 ] do ${t_array[index]}="1" index=$(($index-1)) done
echo $test1 $test2
возвращает ошибку.
Как реализовать присвоение значений заранее заданным переменным?


Ответ

если запустить ваш скрипт, получаем ошибки в девятой строке (содержащей ${t_array[index]}="1"):
/tmp/s: line 9: test2=1: command not found /tmp/s: line 9: test1=1: command not found
т.е. сформированная строка интерпретируется как буквальное выполнение строки test2=1 как команды. такой команды, конечно, нет, о чём интерпретатор и сообщает.
судя по содержимому скрипта, в этом месте необходимо интерпретировать эту строку, чтобы она воспринималась интерпретатором как присвоение значения переменной. это можно сделать, например, добавив команду eval перед выражением, формирующим строку:
eval ${t_array[index]}="1"
тогда скрипт вернёт строку
1 1
что, вероятно, и ожидается.

Решение интеграла в преобразовании Фурье

Есть формула

1-ая это собственно преобразование Фурье,а 2-ая нижняя это формула нахождения спектральной плотности(формула на основе 1-ой),то что я пытаюсь запрограммировать и решить.
Отдельно добавлен класс комплексных чисел чтобы не засорять главную форму.
Такой вопрос,каким методом я могу решить интеграл во 2-ой формуле?
Все поиски увенчались ссылками на alglib,но им запрещено пользоваться(антиплагиат и запрет кафедры на пользование готовыми ресурсами и библиотеками)
Фрагмент кода написанный ниже,это мои попытки воссоздать решение задачи по шагам и по формуле. Но вопрос один,как описать в своей программе интеграл по 2-ой формуле и после записать его в свою функцию.
public double calculate1(double u) { int nmax = 512; int k=0,t=1; double [] Rex=new double[nmax/2+1]; double [] Imx= new double[nmax/2+1]; double[] x = new double[nmax]; double f, w,ur=0,uit=0 ; Complex ct; int U = Convert.ToInt32(textBox1.Text); int T = Convert.ToInt32(textBox2.Text); Rex[k]=0; Imx[k]=0;
for (double j = 0; j <= nmax / 2; j++) { f = 1 / T; w = 2 * Math.PI * f; u=U * Math.Exp( -j * w * t); } uit = U * T;//расчёт значения спектральной плотности амплитуд на нулевой частоте return u; }


Ответ

не буду оценивать верность приведенных формул (и применимость их к решаемой задаче). Допустим тут все норм. А дальше - любой определенный интеграл можно посчитать численным интегрированием. Т.е. интервал [0...тау] разбиваешь на много отрезков (чем больше, тем результат точнее). Далее в цикле вычисляешь значение подинтегральной функции в точке t (например первой точке каждого отрезка), умножаешь на длину отрезка, т.е. получаешь площадь соответствующего прямоугольника, и накапливаешь эти значения. По окончании цикла эта сумма и будет результатом. Ну и для производительности - все значения, которые не зависят от переменной цикла, т.е. от t - вычислять вне цикла, один раз (например в приведенном автором вопроса примере это f и w )

алгоритм поиска в массиве строк наиболее отличающуюся от первой

Я ищу наиболее быстрый алгоритм для поиска строки в массиве строк, которая сильнее всего отличается от первой строки массива. Строки все одинаковой длины. Позиция символов и их ASCII код имеет принципиальное значение. Если решать задачу в лоб, то нужно перебрать каждую строчку массива и сравнить каждый ее символ с символом первой строки с тем же индексом. Если они отличаются, то счетчик для этой строки массива увеличивается. Самый большой счетчик дает нам строку, которая наиболее отличается от первой.


Ответ

Можно использовать следующий алгоритм:
std::vector strings ... std::vector distances; for(size_t i = 1; i < strings.size(); ++i) { std::deque tmp(strings[i].size()); for(size_t j = 0; j < tmp.size(); ++j) tmp[j] = static_cast(strings[i][j] == strings[0][j]); auto distance = count(begin(tmp), end(tmp), false); distances.push_back(distance); } auto idx = distance(begin(distances), max_element(begin(distances), end(distances))) + 1; auto result = strings[idx];
Этот код очень легко переписать под векторные инструкции и его скорость может вырасти многократно, но для этого надо знать размер строк(Вы его знаете, я — нет)

Вариативность функций во FreePascal

Первая ситуация: Есть класс, в котором объявлена процедура
procedure SetDefaultValue(DefValue:integer); procedure SetDefaultValue(DefValue:real); procedure SetDefaultValue(DefValue:string); procedure SetDefaultValue(DefValue:char); procedure SetDefaultValue(DefValue:boolean);
Аналогичные конструкции можно видеть и в родных подключаемых модулях Lazarus, например fpjson. При этом, как я понимаю, будет вызвана та подпрограмма, в аргументах которой указана переменная того же типа, что и переданная в вызове процедуры. Почему это работает, несмотря на отсутствие директивы overload? Когда эту директиву нужно использовать, а когда можно (или нужно) опустить?
Вторая ситуация: Процедуры объявлены в родительском классе
procedure SetDefaultValue(DefValue:integer);dynamic;abstract; procedure SetDefaultValue(DefValue:real);dynamic;abstract; procedure SetDefaultValue(DefValue:string);dynamic;abstract; procedure SetDefaultValue(DefValue:char);dynamic;abstract; procedure SetDefaultValue(DefValue:boolean);dynamic;abstract;
И по одной переопределены в пяти классах потомках, с дерективой override. Будет ли работать такая конструкция и, если нет, то почему?


Ответ

Почему это работает, несмотря на отсутствие директивы overload? Когда эту директиву нужно использовать, а когда можно (или нужно) опустить?
Как нам сообщает документация FreePascal (здесь и далее перевод мой, а ссылки отсюда, в квадратных скобках спорные участки перевода):
Директива overload уведомляет компилятор, что эта функция перегружена. Главным образом, в целях обеспечения совместимости с Delphi, все функции и процедуры во FreePascal могут быть перегружены без использования данной директивы.
Однако, это не означает, что директива overload не используется. Другой раздел той же документации сообщает следующее:
До версии компилятора 1.9 все [объявления] перегруженной функции должны были находиться в одном модуле. Сейчас компилятор продолжает поиск соответствия в других модулях, если не нашёл его в текущем, а функция имеет директиву overload
То есть, директиву overload необходимо использовать только для функций, объявленных в разных модулях вашей программы.
Будет ли работать такая конструкция и, если нет, то почему?
Да, будет.
Однако, не следует использовать подобные конструкции, кроме случаев, когда абстрактные методы объявлены в мета-классах, то есть классах, единственное предназначение которых - хранить поля, свойства и методы, общие для всех классов-потомков мета-класса. Проще говоря, мета-класс - это класс, который никогда не заявляется как тип переменной и экземпляры которого никогда не будут создаваться.
var Meta: TMyMetaClass; //Так с мета-классами делать нельзя.
begin Meta := TMyMetaClass.Create; //И так тоже. end.
Нарушение этого правила однажды закончится для вас страшным геморроем и неуловимыми, как ковбой Джо, ошибками, и вот почему (спасибо Grundy за разъяснения):
Предположим, мы объявили родительский мета-класс A
Type A = Class public val: integer; vals: string; public procedure SetDefaultValue(DefValue:integer);virtual;abstract; procedure SetDefaultValue(DefValue:string);virtual;abstract; end;
И два его класса-потомка, B и C
B = Class(A) public procedure SetDefaultValue(DefValue:integer);override; end; C = Class(A) public procedure SetDefaultValue(DefValue:string);override; end;
Описали наши два метода
procedure B.SetDefaultValue(DefValue:integer); begin val := DefValue; end;
procedure C.SetDefaultValue(DefValue:string); begin vals := DefValue; end;
А затем решили: "А зачем нам объявлять переменные двух разных типов, когда есть наследование?" И написали...
var bb, cc: A;
...получив на свою голову кучу проблем. Потому что такой код:
begin bb := B.Create; bb.SetDefaultValue(10); cc := C.Create; cc.SetDefaultValue(10); end.
Великолепно скомпилируется, чтобы, затем, вызвать ошибку выполнения. Что произошло? Сейчас, на маленьком коде-примере, это понять легко, но словив такую ошибку в многомодульном приложении на три тысячи строк вы рискуете искать её часами, без гарантии, что вообще найдёте. Следите за руками: Мы создали экземпляр класса С
cc := C.Create;
В котором, ранее, переопределили один метод
procedure SetDefaultValue(DefValue:string);override;
Принимающий, в качестве аргумента, переменную типа string. А затем вызвали метод
cc.SetDefaultValue(10);
Передав ему аргумент типа integer. "Но это же должно вызвать ошибку компилятора, почему, тогда программа успешно запустилась?", - спросите вы. Неверно, компилятор не видит в вашем коде ошибки, потому что, формально, её там нет. Напомнить, какого типа переменная cc?
cc: A;
А у класса A есть метод:
procedure SetDefaultValue(DefValue:integer);virtual;abstract;
К которому вы и обращаетесь. Но этот метод - абстрактный, он является лишь указанием для программы искать в области видимости экземпляра класса такой же метод с директивой override, которого она не находит, так как он определён только в классе B, но не C, о чём, при компиляции, вас предупредил Lazarus:
Warning: Constructing a class "С" with abstract method "SetDefaultValue"
Что и вызывает ошибку выполнения. В то же время, такой код:
var bb: B; cc: C;
begin bb := B.Create; bb.SetDefaultValue(10); cc := C.Create; cc.SetDefaultValue(10); end.
Просто вызовет ошибку компиляции на предпоследней строке, которую всегда легко найти и устранить.
Примечание для внимательных читателей: директива dynamic семантически эквивалентна virtual. Первая оптимизирована для памяти, вторая - для скорости.

Работа атрибута ThreadStatic в асинхронных вызовых

Есть библиотека, переделанная под многопоточное выполнение атрибутами ThreadStatic. Есть желание сделать ее асинхронной. Но, как быть со статическими полями и методами? Ведь новый поток не будет создан, и контекст не поменяется...
Это продолжение к прошлому вопросу о атрибуте: ThreadStatic атрибут, тонкости использования


Ответ

Решение можно найти в статье Стивена Клири Implicit Async Context. Я попробую пересказать суть.

Итак, в обыкновеном, не-async-коде, любая цепочка вызовов функций находится всё время в одном и том же потоке. Таким образом, thread static-переменные представляют собой вариант глобальных переменных, которые не подвержены многопоточным проблемам (но имеют проблему с рекурсивным вызовом, конечно).
В случае async-функции, выполнение может «прыгать» между потоками, таким образом, thread local нам не подходит. Что же у нас есть в замену? Что сохраняется при смене потока?
Ответ такой: это «логический контекст вызова», который можно использовать при помощи CallContext.LogicalGetData и CallContext.LogicalSetData. Эти вызовы позволяют записать и считать объект по его строковому имени.
Обычный контекс вызова, доступный через CallContext.GetData и CallContext.SetData, по сути работает как thread local-данные, что не подходит для async-методов.
Логический контекст вызова прикреплён к ExecutionContext'у. Это означает, что на него не влияет ConfigureAwait(continueOnCapturedContext: false). Возможности «отписаться» от сохранения логического контекста нет, он всегда будет передаваться по всем продолжениям (continuations) асинхронного метода.
Когда async-метод начинает выполняться, он сигнализирует логическому контексту вызова активировать отложенное копирование (копирование при фактических измениях). Это значит, что текущий логический контекст не подменяется в реальности немедленно, но как только ваш код вызовет CallContext.LogicalSetData, логический контекст копируется в новый, который становится текущим, и изменения происходят уже на новом контексте. (Обратите внимание: такое поведение имеет место только начиная с .NET 4.5.)
Это значит, что логический контекст работает как стек: изменения в контексте (на верхнем уровне!), внесённые вызываемой функцией, не видны в вызывающей функции. Напротив, изменения, сделанные вызывающей функцией, видны в вызываемой функции.
Копирование логического контекста вызова не глубокое. Проще всего думать о логическом контексте как об IDictionary; при копировании создаётся копия словаря с теми же ключами и ссылками на объекты-значения. Новый словарь ссылается на старые объекты.
Вследствие этого важно не изменять значения внутри объектов, полученных из контекста! Если вам нужно изменить значение, создайте новый объект, и запишите его в контекст при помощи CallContext.LogicalSetData. Лучше всего использовать неизменяемые типы данных, чтобы не поменять значение случайно.
Разумеется, если вы хотите получить данные, изменённые во вложенной функции, вы должны делать всё наоборот: передать изменяемый объект, и изменять значения, записанные в нём. Но такое скорее всего не нужно.
Напоследок: помните, что вы можете попасть в ситуацию, когда изменения видны там, где не должны быть, в двух случаях: (1) версии .NET старше 4.5 не копируют контекст (и значит, локальные изменения становятся глобальными), (2) копирование происходит лишь на верхнем уровне (не рекурсивно), и значит, изменение внутри объекта становится глобальным. Это приведёт к проблемам для кода, в котором поток выполнения ветвится (например, с Task.WhenAll). Поэтому пользуйтесь .NET 4.5+ и неизменяемыми данными!

Как подсказывает @Monk, в .NET Core на текущий момент (Core 2.x) нету аналога CallContext. Используйте в этом случае AsyncLocal, который доступен в .NET Framework 4.6+ и .NET Core 1+. (Вот тут об отличиях между CallContext и AsyncLocal.)