Страницы

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

Показаны сообщения с ярлыком сравнение. Показать все сообщения
Показаны сообщения с ярлыком сравнение. Показать все сообщения

вторник, 25 февраля 2020 г.

С#: сравнение файла на веб-ресурсе и локальный файл

#c_sharp #веб_программирование #файлы #сравнение


Есть веб-сайт, на нем ссылка для скачивая файла "А". Есть локальная версия файла
А. Как можно их сравнить, чтобы не скачивать файл с интернета?

Есть идея  сравнивать контрольные суммы, но для этого файл с инета придется скачать.

Как-то это можно реализовать?
    


Ответы

Ответ 1



Может это поможет? Сравнивать даты. Наткнулся на просторах Интернета. http://www.cyberforum.ru/windows-forms/thread1346241.html

Ответ 2



Только через Head запрос, сервер выдаст информацию о файле в виде заголовка, ну и остальное от сервера зависит, и нужно по ответ Athari проверить заголовки

Ответ 3



Проверьте, поддерживает ли веб-сервер кэширование для файлов. Для этого используются заголовки типа "ETag", "Cache-Control" и другие. Например, если сервер при скачивании файла указывает "ETag", то вы можете запомнить эту строчку и при повторном запросе указать её в заголовке "If-None-Match". Если файл на сервере не изменился, то сервер вернёт вам соответствующий HTTP код (304 Not Modified) с пустым телом ответа, то есть будут скачаны только HTTP заголовки, но не сам файл. См. HTTP ETag.

Ответ 4



Есть элегантное решение с помощью bash однострочника diff myFile <(ssh myHost 'cat myFile') И да можно сравнить два файла которые вообще на разных хостах с помощью третьего хоста. diff <(ssh myHost1 'cat myFile') <(ssh myHost2 'cat myFile') Правда это конечно создаст SSH траффик примерно равный размеру файла, но фактически файл скорее всего не будет скачан на жесткий диск. P.S. Вместо cat можно написать md5sum, а diff заменить на if , чтобы сравнить хэши, совсем избавившись от траффика. Правда в таком случае будет непонятно чем конкретно файлы отличаются.

суббота, 15 февраля 2020 г.

Сравнение двух списков состоящих из массивов

#c_sharp #массивы #список #сравнение


Есть два списка List list1 и list2. Элементы в них могут совпадать. 
Мне нужно получить новый список list3 в который войдут элементы из list2, которых
не было в list1.

Я пытаюсь реализовать это так, но условие не работает и на выходе список пустой.

List list3 = list2.Where(x => !list1.Contains(x)).ToList();


Реализовал это так, но не горел желанием форы использовать, хотелось бы разобраться
почему не работал первый вариант.

for (byte i = 0; i < list2.Count; ++i)
    for (byte j = 0; j < list1.Count; ++j)
        {
            if (list2[i].SequenceEqual(list1[j]))
                list3.Add(list2[i]);
        }

    


Ответы

Ответ 1



Первый вариант не работал потому, что Contains сравнивает через Equals, а равенство по Equals для массивов есть равенство ссылок. А вам ведь нужно SequenceEqual вместо этого. Поэтому можно написать свой вариант Contains: x => !list1.Any(y => y.SequenceEqual(x))

среда, 5 февраля 2020 г.

Сравнение элементов в контейнерном классе array

#cpp #массивы #stl #сравнение


Проблема следующая, есть класс Person с именем и возрастом. Я создаю 2 контейнера
 array, забивая их какими-то экземплярами, и позже хочу сравнить эти контейнеры, на
что получаю ошибку. Оператор сравнения перегрузил, а на ютубе посмотрел, что мол перегрузки
будет достаточно для сравнения

Серьезность Код Описание    Проект  Файл    Строка  Состояние подавления
Ошибка  C2672   "operator __surrogate_func": не найдена соответствующая перегруженная
функция   prikl_programming   c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\xutility
   3084    

`#include 
 #include 
 #include 
 using namespace std;

 class Person {
 public:
 Person(int age, string name) {
    this->age = age;
    this->name = name;
 }
 Person() {
    age = 0;
    name = "null";
 }

 bool operator==(const Person& p) {
    if (this->age == p.age && this->name == p.name)
        return true;
    else
        return false;
 }

 private:
 int age;
 string name;

 friend ostream& operator<<(ostream& os, const Person& p);      
 };

 int main() {

 list l = { Person(1, ""), Person(2, ""), Person(3, "") };
 list l2 = { Person(2, ""), Person(2, ""), Person(3, "") };

 bool flag = (l == l2);
введите сюда код
 system("pause");
 return 0;
 }

 ostream & operator<<(ostream & os, const Person & p)
 {
 cout << p.age << " " << p.name;
 return os;
 }`

    


Ответы

Ответ 1



Попробуйте дать компилятору понять, что ваше сравнение не будет ничего менять в сравниваемых объектах - что это константная функция-член: bool operator==(const Person& p) const { if (this->age == p.age && this->name == p.name) return true; else return false; } (обратите внимание на второй const в первой строке).

Ответ 2



А давайте немного обсудим как лучше строить подобный код. Нужно иметь возможность знать имя или возраст личности, а также придать им новые значения поэтому проще эти поля сделать открытыми. И, так как тип не имеет других полей, то он легко сделается обычной структурой, не имеющей закрытых данных. Конструктор по умолчанию будет означать, что нам неизвестно имя и возраст личности. Он может быть определен посредством вызова имеющегося конструктора с конкретными аргументами. Сама личность не должна иметь функциональность сравнения себя с другой личностью. Такие функции лучше вынести за класс. Исходя из этих соображений напишем улучшенный код, где, кстати, не происходят лишные копировния строк и дальнейшее присваивание в конструкторе (как в вашем случаи): struct Person { int age{}; string name; Person(const int age, const string& name) : age(age), name(name) {} Person() : Person(0, "unknown") {} }; inline bool operator ==(const Person& p1, const Person& p2) { return p1.age == p2.age && p1.name == p2.name; } int main() { list l = { Person(1, ""), Person(2, ""), Person(3, "") }; list l2 = { Person(2, ""), Person(2, ""), Person(3, "") }; bool flag = (l == l2); //... } Такой код нагляднее показывает наши намерения и читабельней...

воскресенье, 12 января 2020 г.

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

#cpp #массивы #алгоритм #поиск #сравнение


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


Ответы

Ответ 1



Можно использовать следующий алгоритм: 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]; Этот код очень легко переписать под векторные инструкции и его скорость может вырасти многократно, но для этого надо знать размер строк(Вы его знаете, я — нет)

вторник, 31 декабря 2019 г.

CompareTo и object

#c_sharp #сравнение


Здравствуйте. У меня появился такой вопрос: зачем в C# метод CompareTo интерфейса
IComparable принимает параметр типа object? Не проще ли принимать параметр того же
типа IComparable? Заранее спасибо    


Ответы

Ответ 1



В .NET на самом деле есть оба интерфейса: IComparable и IComparable. Первый сохраняется как наследие со времён .NET 1.x, в котором не было обобщённых типов (генериков). Для старого IComparable каким может быть тип аргумента функции CompareTo? Это должен быть один тип на все возможные случаи использования, для сравнения любого типа с собой, так что единственное, что может в принципе подойти, это object. Для нового IComparable мы можем объявить возможность сравнения с любым типом Т, которым захотим. Разумеется, никто не помешает написать class A : IComparable { ... — но правильное использование интерфейса, конечно, для сравнения с объектами того же самого типа: class A : IComparable<А> { ... К сожалению, система типов .NET на текущий момент недостаточно сильна, чтобы выразить ограничение «тип, сравнимый с самим собой», а не просто «тип, сравнимый с данным типом». Если вам интересны языки с более развитой системой типов, гляньте в сторону функциональных языков.

Ответ 2



Этого достаточно Это намного проще с точки зрения дизайна языка. Например, вы пишите метод сортировки и объявляете его как void Sort(IList list) where T : IComparable тем самым давая возможность сортировать объекты любых сравнимых типов. Единственный способ сделать строготипизированный интерфейс IComparable, это объявить его как interface IComparable { int CompareTo(T obj); } Но тогда никто не запретит вам сделать это class Foo : IComparable, IComparable {...} Что, согласитесь, совсем не логично.

Как сравнить float и double?

#cpp #float #сравнение #double


Как правильно сравнивать два числа типа float и double? Следующий способ часто говорит,
что одинаковые числа различны:

float a = 0.00001001;
double b = 0.00001001;

if (a == b) {
  std::cout << "equal"; // не выводит equal
}


Мой вопрос отличается от дубликатов тем, что мне нужно знать, как правильно сравнить
2 числа типа float и double на C++, а не почему (не только почему) простое сравнение
не работает. В привидённых в дубликатах ответах либо ответы для 2 одинаковых типов,
либо не сказано как выбирать epsilon и т.д..
    


Ответы

Ответ 1



if (fabs(a - b) <= eps) где eps - некая маленькая величина, вообще говоря - зависящая от порядка самих чисел, поэтому более корректно if (fabs(a - b)/ max(fabs(a) + eps, fabs(b) + eps) <= eps) Пример задания eps: const FuzzFactor = 1000; SingleResolutionEps = 1E-7 * FuzzFactor; DoubleResolutionEps = 1E-15 * FuzzFactor; Откуда это берётся - точность float 23 двоичных разряда или 7-8 десятичных, т.е. число имеет 7 верных десятичных цифр, поэтому меньше 1E-7 eps смысла нет делать. Почему используется множитель FuzzFactor = 1000; - это расширение допуска, чёткого критерия его выбора нет, разработчики этой библиотеки решили так сделать, а вообще множитель можно выбирать в зависимости от желаемой погрешности в младших разрядах. Для сравнения float и double по правилам сложения погрешностей следует использовать погрешность для менее точных float, т.е. порядка 1E-7 даже при приведении float к double, как предложил в комментарии @Grundy - ведь при этом приведении возникают дополнительные ничем не обеспеченные разряды с погрешностью в пределах всё тех же 1E-7. Труды по точности float-арифметики: 1 2 Goldberg

Ответ 2



Машинный эпсилон это одно,а точность входных данных в задаче это совсем другое. Редко бывает, чтобы точность входных данных в задаче была равна машинному эпсилону. Обычно точность входных данных в задаче гораздо меньше, чем машинный эпсилон. Есть целая наука об правилах округления и отбрасывания незначащих цифр. Исходя из этой науки и выбирается в каждом конкретном случае эпсилон для каждой конкретной задачи. А машинный эпсилон это характеристика данной вычислительной системы.

суббота, 21 декабря 2019 г.

Как скомпрессировать набор натуральных чисел? Порядок неважен, повторов нет.

#множества #сжатие #алгоритм #сравнение #компрессия


Задача сравнить два набора уникальных целых положительных чисел, и найти присутствующие
сразу в обоих. Все точно лежат в диапазоне от 1 до 200 млн. Обычно в каждом из двух
наборов от 0 до 5 млн чисел.
До сих пор делаю "в лоб": оба сета заношу во временные таблицы MySQL. Две одноколоночные
таблицы, где числа – первичные ключи. Сравнение проходит быстро, если сеты маленькие
и помещаются в engine=MEMORY. Медленно, когда таблицы большие и приходится создавать
их на диске. Когда надо таких сравнений выполнять помногу и часто — тормоза.
Что, если воспроизвести индексированные колонки MySQL в собственном коде? Один из
сетов держать в памяти, а каждый элемент второго проверять на наличие в первом.
Не хранить каждое из чисел набора (32бит, 2.5млн в среднем = 80Мб), а работать с
битовой маской всех возможных значений. 200 млн это, с запасом, 2^28 = 268,435,456
бит = 32Мб. Установлен – число есть в наборе, 0 – нет. Сравнивать установленные биты. 
В полном виде хранить для каждого сета весь набор битов неэффективно. Наверняка,
можно такие данные здорово компрессировать. Большинство битов будут 0, значит, их последовательности
можно кодировать их кол-вом подряд например. 
Вопрос к такому компрессированному массиву будет один: есть ли очередное искомое
число в наборе, или нет?
Упростим для примера. Пусть всего может быть 32 значения: 0..31. Наш массив будет
состоять из 32 нулей/единиц. В наборе присутствуют всего два значения: 17 и 22. 16
нулей, единица, 4 нуля, 1. И запишем их как 16,4: 10000100. Всего 8 бит вместо 2*6.
компрессия сэкономила 25%. Но это моё совсем косолапое представление о возможном способе
компрессии, без разделителей, единиц подряд и т.п.
Надо узнать про число 19, есть ли в наборе? Проходим по нашим 8 битам: 16 ещё пока
меньше 19, ещё 4 — уже перебор, ответ "нет в наборе".
Как по-вашему, есть ли вообще смысл в таком велосипеде, может ли он ускорить сравнение
двух сетов, по сравнению с MySQL?
Upd. Проще сформулирую вопрос. Ищется компрессия для данных, когда известны их параметры
и ограничения: только натуральные числа от .. до .., не подряд, не сортированные, без
повторов, порядок неважен. И даже без необходимости распаковки: нужно лишь уметь ответить
на вопрос «есть ли такое-то число в наборе, или нет?».    


Ответы

Ответ 1



1) БД не для решения таких задач 2) используем либо упорядоченные списки, либо хештаблицы 3) я бы использовал упорядоченный список или массив, и потом сравнивал методом попарного слияния: - оба указателя на первые элементы берем элемент с первого списка, сравниваем с элементом второго списка если значения равны, то элемен заносим в список результата и увеличиваем оба указателя и к пп 1 если 1 < 2, увеличиваем значение указателя первого списка иначе второго итого, используемые алгоритмы: 2 * qsort и попарного слияния если списки ну очень большие...(20 млн вполне терпимо для памяти, но 200 может быть уже перебором), то их можно разбить на части и сравнивать сперва часть 1, потом часть 2. Алгоритм приблизительно следующий: есть списки 1: А+Б+С+Д... и 2:А+Б+С+Д... - сравниваем список 1А и 2А если список 1А закончился, то сравниваем конец списка 2А и список 1Б иначе конец списка 2Б со списоком 1А как только какой список заканчивается текущим становится следующий из данной последовательности (1 или 2 ) и так далее

Ответ 2



Я бы начал с простых решений и замеров времени выполнения для разных наборов данных. Вы можете всегда хранить данные в заранее подготовленном виде (Например уже в бинарном дереве или в отсортированном массиве)? Тогда находить элементы можно примерно так: // для отсортированным массивов. Сложность О(a.length + b.length) public static List GetSameNumber(Int32[] a, Int32[] b) { var i = 0; var j = 0; var ans = new List(); while (i < a.Length && j < b.Length) { if (a[i] == b[j]) { ans.Add(a[i]); i++; j++; } else if (a[i] > b[j]) j++; else i++; } return ans; } // для бинарных деревьев. Сложность О(a.length) или О(a.length + b.length)в зависимости от реализации public static List GetSameNumber(SortedSet a, SortedSet b) { var ans = new List(); foreach (var i in a) { if (b.Contains(i)) ans.Add(i); } return ans; //var ansset = new SortedSet(a); //ansset.IntersectWith(b); //return ansset.ToList(); // или просто return ansset } Если данные нельзя хранить в нужном виде, то переводить в него каждый раз при вызове. Тут появляется О(nlogn) для создания бинарного дерева или сортировки массива. Большое дерево с битами на 8Гб наверно даст пенальти по кешу и пейджингу.

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

Каков принцип работы метода compareTo()?

#java #сравнение


Кто может объяснить принцип сравнения, когда есть разные варианты сравниваемых строк,
которые могут отличаться как буквами, так и длиной?
    


Ответы

Ответ 1



Строки в Java(и вообще много где) сравниваются с помощью Лексикографического порядка. О том, что это такое можно почитать так же тут. Общий смысл, по алфавиту. Если говорить именно про класс String, то он реализует интерфейс Comparable в документации подробно описано, что должен возвращать метод compareTo(). Если вкратце, то он определяет порядок элементов. o1.compateTo(o2): > 0 - если o1 должен идти после o2 (в случаем с числами o1>o2, со строками, по алфавиту o2 идёт раньше o1) =0 - если o1 и o2 равнозначны (не обязательно равны! НО, если o1.equals(o2) == true, то желательно, чтобы o1.compareTo(o2) == 0, иначе теряется консистентность) <0 - если o1 должен идти перед o2 (в случаем с числами o1

суббота, 14 декабря 2019 г.

Как вывести различия в двух массивах?

#javascript #массивы #сравнение


Например, есть 2 массива:

var days      = ["Понедельник", "Вторник", "Среда", "Четверг", 
    "Пятница", "Суббота", "Воскресенье"];
var work_days = ["Понедельник", "Вторник", "Среда", "Четверг", 
    "Пятница", "Рабочие дни"];


Как их сравнить и вывести результат: 

"Суббота", "Воскресенье", "Рабочие дни"

    


Ответы

Ответ 1



Можно примерно так: var days = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"]; var work_days = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Рабочие дни"]; document.body.innerText = JSON.stringify( diff(days, work_days)); function diff( a, b) { var diff = a.filter((e)=>!~b.indexOf(e)); return diff.concat(b.filter((e)=>!~a.indexOf(e))); } В функцию сравнения diff() передаём оба массива. Там с помощью метода .filter(), сначала отбираются те элементы a, которых нет в b. А затем к полученным добавляются наоборот – те из b, которых нет в a. Использованы методы: склейка массивов .concat(), фильтр массива .filter()

Ответ 2



Можно подготовить один из массивов и собрать из него объект, с помощью функции reduce, это позволит избавиться от indexOf var days = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье" ]; var work_days = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Рабочие дни" ]; document.body.innerText = JSON.stringify(diff(days, work_days)); function diff(a, b) { var m = days.reduce(function(a, d) { a[d] = 1; return a; }, {}); var r = work_days.reduce(function(acc, el) { delete acc.rest[el]; if (!acc.m[el]) acc.result.push(el); return acc; }, { m: m, result: [], rest: Object.assign({}, m) }); return r.result.concat(Object.keys(r.rest)); }

Ответ 3



Операция известная и реализована в куче библиотек. Один из вариантов — lodash.xor: var days = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"]; var work_days = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Рабочие дни"]; var result = _.xor(days, work_days); alert(result);

Ответ 4



решение за O(n) по времени и O(n) по памяти и требующее не повторящихся элементов в массивах. var days = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"]; var workDays = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Рабочие дни"]; var diff = []; var daysAsKeys = new Map(); // need ES6 days.forEach(function(day) { daysAsKeys.set(day, true); }); var workDaysAsKeys = new Map(); workDays.forEach(function(workDay) { workDaysAsKeys.set(workDay, true); }); days.forEach(function(day) { if (!workDaysAsKeys.has(day)) diff.push(day); }); workDays.forEach(function(workDay) { if (!daysAsKeys.has(workDay)) diff.push(workDay); }); alert(diff)

четверг, 12 декабря 2019 г.

Сравнение строк, содержащих числа

#javascript #строки #сравнение


Почему при сравнении двух строк "70px" и "622px" первое значение оказывается больше?
    


Ответы

Ответ 1



Как сравнить числа, содержащиеся в строках, рассказано в ответе @11111000000. А я расскажу о том, почему такое происходит при сравнении самих строк. Строки сравниваются с помощью лексикографического порядка. Лексикографически "70px" больше, чем "622px" (т.к. символ "7" идет после символа "6"). Лексикографический порядок — отношение линейного порядка на множестве слов длины n над некоторым упорядоченным алфавитом ∑. Своё название лексикографический порядок получил по аналогии с сортировкой по алфавиту в словаре. Слово a предшествует слову b (a

Ответ 2



просто никогда не сравнивайте строки иначе, нежели == и != . Почему это так работает, знать конечно познавательно, однако на практике: parseFloat('70px', 10) - и только так. Не parseInt, ибо в CSS размеры могут быть с дробными долями.

Ответ 3



Символ '7' больше символа '6', поэтому первая строка больше второй строки. Сравнение происходит посимвольно в соответствии с кодами символов.

суббота, 7 декабря 2019 г.

Как сравнить два csv файла

#c_sharp #csv #сравнение


Есть 2 csv файла с содержимым

1.csv

spain;russia;japan
italy;russia;france


2.csv

spain;russia;japan
india;iran;pakistan


Считываю оба файла и заношу их содержимое в список

var lst1= File.ReadAllLines("1.csv").ToList();
var lst2= File.ReadAllLines("2.csv").ToList();


Затем я ищу уникальные элементы из обоих списков

var rezList = lst1.Except(lst2).Union(lst2.Except(lst1)).ToList();


В rezlist у нас следюущие данные.

[0] = "italy;russia;france"
[1] = "india;iran;pakistan"


Теперь же я хочу сравнить оба csv-файла по второй и третьей колонке. Как мы выдими
разделители колонок у нас ;

class StringLengthEqualityComparer : IEqualityComparer
    {

        public bool Equals(string x, string y)
        {
            return (x.Split(';')[1] == y.Split(';')[1] && x.Split(';')[2] == y.Split(';')[2]);
        }

        public int GetHashCode(string obj)
        {
            return obj.Split(';')[1].GetHashCode();
        }
    }

 StringLengthEqualityComparer stringLengthComparer = new StringLengthEqualityComparer();
 var rezList = lst1.Except(lst2,stringLengthComparer ).Union(lst2.Except(lst1,stringLengthComparer),stringLengthComparer).ToList();


Вопрос. Как правильно составить класс StringLengthEqualityComparer чтобы он искал
уникальные значения по двум колонкам?
    


Ответы

Ответ 1



Интерфейс IEqualityComparer предоставляет возможность расширения или замены логики сравнения объектов. Он используется, например, в таких структурах, как Dictionary и HashSet, а также в некоторых методах, которые активно пользуются сравнением объектов (как например использованный вами метод расширения Except()). Как известно, для того, чтобы иметь возможность корректно сравнивать объекты, в них должны быть переопределены методы Equals() и GetHashCode(), причем должны соблюдаться следующие условия: стандартные условия для равенства (например, транзитивность) два равных объекта должны давать одинаковое значение хэшкода (При этом два разных объекта могут иметь равные хэшкоды -- это называется коллизией и должно случаться как можно реже.) Оба этих метода активно используются структурами Dictionary, HashSet, а также внутренним классом Set, который используется в методе Except(). В случае, когда мы не хотим или не имеем возможности изменять логику сравнения для существующих типов, на помощь нам и приходит интерфейс IEqualityComparer -- вместо вызовов методов Equals() и GetHashCode() у самих объектов, эти методы вызываются у компаратора. Именно поэтому этот интерфейс содержит оба метода, а не один Equals(). А также именно поэтому реализация компаратора должна соблюдать обозначенные выше условия. Приведенная вами реализация компаратора дает корректные результаты сравнения, однако при большом объеме данных может свести на нет все преимущества быстрой работы метода Except(). Для пар a;b и a;c выдастся одинаковый хэшкод, они попадут в одну корзину внутри Set, что ухудшает показатели скорости работы (подробнее читайте в статьях о том, как работают хэш-таблицы). Поэтому правильная реализация должна использовать те же поля, которые используются в Equals(), т.е. колонки 1 и 2 (про хэш-функции также читайте в статьях о хэш-таблицах). Например: public int GetHashCode(string obj) { var valuesArray = obj.Split(';') int hashcode = valuesArray[1].GetHashCode(); hashcode = hashcode * 31 + valuesArray[2].GetHashCode(); return hashcode; } На этом реализация компаратора закончена. Однако в целом производительность такого решения оставляет желать лучшего. Поскольку вы вызываете Except() дважды, то для каждой пары строк из обоих файлов методы компаратора (по крайней мере, GetHashCode()) будут вызываться дважды. Вкупе с избыточными разбиениями внутри этих методов картина получается нерадостная. Можно пойти по другому пути, например, заранее разбить строки: var splittedLst1 = lst1.Select(i => i.Split(';')); var splittedLst2 = lst2.Select(i => i.Split(';')); Затем получить разницу: var comparer = new StringLengthEqualityComparer(); var rezList = splittedLst1 .Except(splittedLst2, comparer) .Union(splittedLst2.Except(splittedLst1, comparer)); А при необходимости снова склеить строки: foreach (var item in rezList) { Console.WriteLine(string.Join(";", item)); } При таком подходе каждая строка будет разбита всего один раз, а код компаратора упростится: class StringLengthEqualityComparer : IEqualityComparer { public bool Equals(string[] x, string[] y) { return x[1] == y[1] && x[2] == y[2]; } public int GetHashCode(string[] obj) { var hashcode = obj[1].GetHashCode(); hashcode = hashcode * 31 + obj[2].GetHashCode(); return hashcode; } } Если вы ожидаете строки разной длины (в смысле количества колонок), то нужно изменить компаратор таким образом, чтобы он корректно работал со строками разной длины. Провел небольшой тест для сравнения производительности. В качестве тестовых данных склеил 10000 раз приведенные вам двухстрочники. Разница в результатах при этом получилась следующая: Radzhab: 332ms andreycha: 63ms

Ответ 2



Как уже написали в комментариях, лучше отказаться от IEqualityComparer, т.к., имхо, это попытка заставить кота лаять. У нас единицы информации — это "ячейки", т.е. слова конкретные, оперирование строками с этими словами порождает неудобные и багоопасные конструкции с прямым индексированием (кстати, легковесное в теории сравнение превратилось в 4-кратный вызов разбиения строки на подмассив; даже по алгоритму достаточно двух раз), что собственно ни к чему, если изначально всё разбить на слова. Т.е. в чём оптимизация, если выделяется больше памяти, больше операций и прямые индексы? Сперва, на мой взгляд надо подготовить строки, т.е. в нашем случае можно всё загнать просто в двумерный массив строк, и все операции производить в нём, с отдельными словами.

Ответ 3



private void GetUnion(List lst1, List lst2) { // List для результата List lstUnion = new List(); foreach (string value in lst1) { string valueColumn1 = value.Split(';')[0]; string valueColumn2 = value.Split(';')[1]; string valueColumn3 = value.Split(';')[2]; // Ищем совпадения, есть ли valueColumn2 и valueColumn3 в lst2 во 2-й и 3-й колонке, // С 1-й и 2-й не перепутаем, // ";russia;japan" - такая последовательность со знаком ';' в начале // может быть только если текст начинается со второй колонки. string result = lst2.FirstOrDefault(s => s.Contains(";" + valueColumn2 + ";" + valueColumn3)); if (result != null) // если совпадения есть { if (!lstUnion.Contains(result)) // и если значение уже не добавлено { lstUnion.Add(result); MessageBox.Show(result); // для проверки } } } // В итоге в lstUnion одно значение - "spain;russia;japan" }

Ответ 4



Открываешь .csv как двумерный массив данных с помощью: Как просто работать с / открыть / изменить / сохранить Excel / CSV файлы Сравниваешь сначала по количеству ячеек в массивах, а потом если оно одинаковое, то по нутрянке ячеек двумя foreach (один во втором). :)

Преобразование скалярных типов при сравнении JavaScript

#javascript #типы_данных #сравнение


Объясните, пожалуйста, почему из трех алертов ниже исполняется только последний?
Вроде как во всех трёх случаях идет мягкое сравнение на равенство к true

if (true == "0") alert('Тру равно нулю!');

if ("0" == true) alert('Ноль равен тру');

if ("0") alert('Как бы тоже тру, или как?');


https://jsfiddle.net/z1xbshmk/
    


Ответы

Ответ 1



Стоит обратиться к спецификации При вычислении равенства EqualityExpression == RelationalExpression получаются значения левой и правой части, и к ним применяется Abstract Equality Comparison. Сравнение x == y, где x и y - значения, возвращает true or false. Такое сравнения производится следующим образом: Если Type(x) тот же самый, что и Type(y), тогда возвращается результат выполнения Strict Equality Comparison x === y. Если x является null и y является undefined, вернуть true. Если x является undefined и y является null, вернуть true. Если Type(x) - это Number и Type(y) - это String, вернуть результат выражения x == ToNumber(y). Если Type(x) - это String и Type(y) - это Number, вернуть результат выражения ToNumber(x) == y. Если Type(x) - это Boolean, вернуть результат выражения ToNumber(x) == y. Если Type(y) - это Boolean, вернуть результат выражения x == ToNumber(y). Если Type(x) один из следующих: String, Number, или Symbol и Type(y) это Object, вернуть значение выражения x == ToPrimitive(y). Если Type(x) - это Object и Type(y) один из следующих: String, Number, или Symbol, вернуть значение выражения ToPrimitive(x) == y. Вернуть false. Рассмотрим первый пример: true == "0" Это выражении соответствует ветке Если Type(x) - это Boolean, вернуть результат выражения ToNumber(x) == y. При приведении к числу получаем выражение: 1 == "0" попадаем в ветку Если Type(x) - это Number и Type(y) - это String, вернуть результат выражения x == ToNumber(y). При приведении к числу получаем выражение: 1 == 0 и как результат: false. Со вторым случаем происходит аналогичное. Теперь рассмотрим третий случай. Обратимся опять к спецификации: К выражению внутри скобок применяется функция ToBoolean, которая в случае строки возвращает false если строка пустая(длина строки 0), и true - в противном случае. Так как "0" - не пустая(длина строки 1), то условие считается выполненным.

Ответ 2



Строка таки преобразуется в ноль, что трактуется как ложь. То же самое, только наоборот аргументы. Это не пустая строка, трактуется как true. Как оно происходит.

суббота, 30 ноября 2019 г.

Как определить степень схожести двух текстов?

#алгоритм #сравнение #wavelet #текст


Допустим, взяли исходный текст, три абзаца. В его копии убрали полностью последнее
предложение, поменяли адрес ссылки где-то в тексте, заменили пару предлогов, и заменили
пару слов на синонимы.
Каков алгоритм, чтобы определить "эти тексты сходны на 65%. Скорее всего, общий первоисточник"?
Есть ли что-то вроде вэйвлет анализа для текстов?     


Ответы

Ответ 1



В биоинформатике подобные вопросы - определение схожести двух разных последовательностей нуклеиновых кислот или протеинов (читай - текстов) - составляют основную проблему. Решается она с помощью разных алгоритмов выравнивания. В вашем случае можно применить метод глобального выравнивания - самого простого из них. Подробнее о нем читай по указанной ссылке. Если будет непонятно, порекомендую литературу.

Ответ 2



Алгоритм шинглов. Алгоритм шинглов — алгоритм, разработанный для поиска копий и дубликатов рассматриваемого текста в веб-документе, мощный инструмент, призванный бороться с проявлениями плагиата в интернете.

Ответ 3



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

воскресенье, 24 ноября 2019 г.

Как сравнивать строки в Java?


В своей программе я использовал оператор == для сравнения строк. Но я наткнулся на баг, и при замене == на equals он пропал.​​​​​​​​​​

Следует избегать оператора ==? Когда его можно использовать, а когда нет? В чём разница?
    


Ответы

Ответ 1



Оператор == сравнивает ссылки. Метод equals сравнивает значения. Следовательно, если вы хотите сравнить строки на равенство, следует использовать equals. Однако в некоторых случаях строки гарантированно представлены одним и тем же объекто благодаря пулу строк (string interning). Эти случаи явно описаны в спецификации языка Java. Оператор == используется для проверки, что две строки указывают на один и тот же объект. // Эти строки имеют одно и тоже же значение new String("test").equals("test") // --> true // ...но это разные объекты new String("test") == "test" // --> false // ...эти строки тоже разные объекты new String("test") == new String("test") // --> false // ...но эти строки указывают на один и тот же объект, // потому что компилятор добавляет все литералы в пул. "test" == "test" // --> true // Конкатенация литералов тоже происходит на стадии компиляции, // поэтому они указывают на один объект "test" == "te" + "st" // --> true // но вызов substring() происходит во время выполнения, // в результате получаются разные объекты. "test" == "!test".substring(1) // --> false // Строки из пула могут быть получены с помощью вызова intern(). "test" == "!test".substring(1).intern() // --> true Надо отметить, что == заметно быстрее, чем equals (сравнение ссылки вместо вызов метода и посимвольного сравнения, если строки разной длины), поэтому, если вы работаете со строками из пула (или системного, или своего), замена equals на == может привести к заметному ускорению. Но это случается очень редко. Остерегайтесь вызова equals на null! Оператор == прекрасно сравнивает строки, есл одна или более из них равна null, но вызов метода equals на строке, равной null, приведёт к исключению. Для сравнения строк, которые могут быть равны null, вы можете воспользоваться следующим методом: public static boolean equals(String str1, String str2) { return str1 == null ? str2 == null : str1.equals(str2); } Он присутствует в некоторых сторонних библиотеках, например, в Apache Commons. Если вы пользуетесь современными средами разработки, то они предупредят, если в попытаетесь сравнить строки с помощью оператора ==. Всегда обращайте внимание на подобные предупреждения.

Ответ 2



Если быть коротко, то == сравнивает ссылки на объект, если ссылки указывают на оди и тот же объект, то это тру, иначе false, в случае с примитивными типами == сравнивает значения. equals () используется в String так, он берет и сравнивает посимвольно каждый String но это только со String, если брать остальные объекты (Вы создали объекты Яблоко и Груша), при этом в этих классах не прописан метод equals,то оно как и == сравнивает ссылки на объект, если это один и тот же объект, то тру иначе false. В String прописан метод equals (), который сравнивает посимвольно, поэтому со String нужно юзать equals ()

вторник, 14 мая 2019 г.

С#: сравнение файла на веб-ресурсе и локальный файл

Есть веб-сайт, на нем ссылка для скачивая файла "А". Есть локальная версия файла А. Как можно их сравнить, чтобы не скачивать файл с интернета?
Есть идея сравнивать контрольные суммы, но для этого файл с инета придется скачать.
Как-то это можно реализовать?


Ответ

Может это поможет? Сравнивать даты. Наткнулся на просторах Интернета. http://www.cyberforum.ru/windows-forms/thread1346241.html

четверг, 25 апреля 2019 г.

Сравнение двух списков состоящих из массивов

Есть два списка List list1 и list2. Элементы в них могут совпадать. Мне нужно получить новый список list3 в который войдут элементы из list2, которых не было в list1
Я пытаюсь реализовать это так, но условие не работает и на выходе список пустой.
List list3 = list2.Where(x => !list1.Contains(x)).ToList();
Реализовал это так, но не горел желанием форы использовать, хотелось бы разобраться почему не работал первый вариант.
for (byte i = 0; i < list2.Count; ++i) for (byte j = 0; j < list1.Count; ++j) { if (list2[i].SequenceEqual(list1[j])) list3.Add(list2[i]); }


Ответ

Первый вариант не работал потому, что Contains сравнивает через Equals, а равенство по Equals для массивов есть равенство ссылок. А вам ведь нужно SequenceEqual вместо этого.
Поэтому можно написать свой вариант Contains
x => !list1.Any(y => y.SequenceEqual(x))

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

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

Я ищу наиболее быстрый алгоритм для поиска строки в массиве строк, которая сильнее всего отличается от первой строки массива. Строки все одинаковой длины. Позиция символов и их 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];
Этот код очень легко переписать под векторные инструкции и его скорость может вырасти многократно, но для этого надо знать размер строк(Вы его знаете, я — нет)

вторник, 8 января 2019 г.

CompareTo и object

Здравствуйте. У меня появился такой вопрос: зачем в C# метод CompareTo интерфейса IComparable принимает параметр типа object? Не проще ли принимать параметр того же типа IComparable? Заранее спасибо


Ответ

В .NET на самом деле есть оба интерфейса: IComparable и IComparable. Первый сохраняется как наследие со времён .NET 1.x, в котором не было обобщённых типов (генериков). Для старого IComparable каким может быть тип аргумента функции CompareTo? Это должен быть один тип на все возможные случаи использования, для сравнения любого типа с собой, так что единственное, что может в принципе подойти, это object Для нового IComparable мы можем объявить возможность сравнения с любым типом Т, которым захотим. Разумеется, никто не помешает написать class A : IComparable { ... — но правильное использование интерфейса, конечно, для сравнения с объектами того же самого типа: class A : IComparable<А> { ... К сожалению, система типов .NET на текущий момент недостаточно сильна, чтобы выразить ограничение «тип, сравнимый с самим собой», а не просто «тип, сравнимый с данным типом». Если вам интересны языки с более развитой системой типов, гляньте в сторону функциональных языков.

понедельник, 12 ноября 2018 г.

Как скомпрессировать набор натуральных чисел? Порядок неважен, повторов нет.

Задача сравнить два набора уникальных целых положительных чисел, и найти присутствующие сразу в обоих. Все точно лежат в диапазоне от 1 до 200 млн. Обычно в каждом из двух наборов от 0 до 5 млн чисел. До сих пор делаю "в лоб": оба сета заношу во временные таблицы MySQL. Две одноколоночные таблицы, где числа – первичные ключи. Сравнение проходит быстро, если сеты маленькие и помещаются в engine=MEMORY. Медленно, когда таблицы большие и приходится создавать их на диске. Когда надо таких сравнений выполнять помногу и часто — тормоза. Что, если воспроизвести индексированные колонки MySQL в собственном коде? Один из сетов держать в памяти, а каждый элемент второго проверять на наличие в первом. Не хранить каждое из чисел набора (32бит, 2.5млн в среднем = 80Мб), а работать с битовой маской всех возможных значений. 200 млн это, с запасом, 2^28 = 268,435,456 бит = 32Мб. Установлен – число есть в наборе, 0 – нет. Сравнивать установленные биты. В полном виде хранить для каждого сета весь набор битов неэффективно. Наверняка, можно такие данные здорово компрессировать. Большинство битов будут 0, значит, их последовательности можно кодировать их кол-вом подряд например. Вопрос к такому компрессированному массиву будет один: есть ли очередное искомое число в наборе, или нет? Упростим для примера. Пусть всего может быть 32 значения: 0..31. Наш массив будет состоять из 32 нулей/единиц. В наборе присутствуют всего два значения: 17 и 22. 16 нулей, единица, 4 нуля, 1. И запишем их как 16,4: 10000100. Всего 8 бит вместо 2*6. компрессия сэкономила 25%. Но это моё совсем косолапое представление о возможном способе компрессии, без разделителей, единиц подряд и т.п. Надо узнать про число 19, есть ли в наборе? Проходим по нашим 8 битам: 16 ещё пока меньше 19, ещё 4 — уже перебор, ответ "нет в наборе". Как по-вашему, есть ли вообще смысл в таком велосипеде, может ли он ускорить сравнение двух сетов, по сравнению с MySQL? Upd. Проще сформулирую вопрос. Ищется компрессия для данных, когда известны их параметры и ограничения: только натуральные числа от .. до .., не подряд, не сортированные, без повторов, порядок неважен. И даже без необходимости распаковки: нужно лишь уметь ответить на вопрос «есть ли такое-то число в наборе, или нет?».


Ответ

1) БД не для решения таких задач 2) используем либо упорядоченные списки, либо хештаблицы 3) я бы использовал упорядоченный список или массив, и потом сравнивал методом попарного слияния: - оба указателя на первые элементы берем элемент с первого списка, сравниваем с элементом второго списка если значения равны, то элемен заносим в список результата и увеличиваем оба указателя и к пп 1 если 1 < 2, увеличиваем значение указателя первого списка иначе второго итого, используемые алгоритмы: 2 * qsort и попарного слияния если списки ну очень большие...(20 млн вполне терпимо для памяти, но 200 может быть уже перебором), то их можно разбить на части и сравнивать сперва часть 1, потом часть 2. Алгоритм приблизительно следующий: есть списки 1: А+Б+С+Д... и 2:А+Б+С+Д... - сравниваем список 1А и 2А если список 1А закончился, то сравниваем конец списка 2А и список 1Б иначе конец списка 2Б со списоком 1А как только какой список заканчивается текущим становится следующий из данной последовательности (1 или 2 ) и так далее

четверг, 8 ноября 2018 г.

Каков принцип работы метода compareTo()?

Кто может объяснить принцип сравнения, когда есть разные варианты сравниваемых строк, которые могут отличаться как буквами, так и длиной?


Ответ

Строки в Java(и вообще много где) сравниваются с помощью Лексикографического порядка. О том, что это такое можно почитать так же тут. Общий смысл, по алфавиту.
Если говорить именно про класс String, то он реализует интерфейс Comparable в документации подробно описано, что должен возвращать метод compareTo(). Если вкратце, то он определяет порядок элементов.
o1.compateTo(o2)
> 0 - если o1 должен идти после o2 (в случаем с числами o1>o2, со строками, по алфавиту o2 идёт раньше o1)
=0 - если o1 и o2 равнозначны (не обязательно равны! НО, если o1.equals(o2) == true, то желательно, чтобы o1.compareTo(o2) == 0, иначе теряется консистентность)
<0 - если o1 должен идти перед o2 (в случаем с числами o1