Есть строка QString DDF1 с n элементами (устройства USB)
Есть строка QString DDF2 с n+1 элементами (добавили флешку)
Нужно получить название этой флешки, но проблема в том, что оно может быть добавлено в середину текста...
Пример:
Ввод:
/dev/sda /dev/sda1 /dev/sdc /dev/sdc1
/dev/sda /dev/sda1 /dev/sdb /dev/sdb1 /dev/sdc /dev/sdc1
Вывод:
/dev/sdb /dev/sdb1
Что-то вроде того:
QString str1{"/dev/sda /dev/sda1 /dev/sdc /dev/sdc1"};
QString str2 { "/dev/sda /dev/sda1 /dev/sdb /dev/sdb1 /dev/sdc /dev/sdc1" }
auto list1 = str1.split(" ");
auto list2 = str2.split(" ");
list1.sort();
list2.sort();
QStringList retval{};
auto secondIter = list1.begin();
for (auto i = list2.begin(); i != list2.end;) {
if (secondIter == list1.end()) {
retval.push_back(*i);
++i;
} else {
if (*i != *secondIter) {
retval.push_back(*secondIter);
++secondIter;
}
}
}
for (; secondIter != list1.end(); ++secondIter) {
retval.push_back(*secondIter);
}
Код не проверял, но, думаю, направление вы уловите.
Вот предлагаю по-оптимизировать. Использовать класс QStringRef чтобы лишний раз не копировать строки, и сравнивать хэши:
#include <QVector>
#include <QHash>
template<typename V>
using Hashes = QVector<QPair<uint, V>>;
template<typename V>
Hashes<V> HashItems(const QVector<V> & items)
{
Hashes<V> result;
result.reserve(std::size(items));
for(const auto & i: items)
{
result.emplace_back(QHash::qHash(i), i);
}
return result;
}
QVector<QStringRef> diff(const QString & str1, const QString & str2)
{
auto tokens1 = HashItems(str1.splitRef(" "));
auto tokens2 = HashItems(str2.splitRef(" "));
// оптимизация, из короткого удалять дешевле
const auto & large = std::size(tokens1) > std::size(tokens2) ? tokens1 : tokens2;
auto & small = std::size(tokens1) <= std::size(tokens2) ? tokens1 : tokens2;
QVector<QStringRef> result;
for(const auto & l : large)
{
bool unique = true;
for(auto s = std::begin(small); s != std::end(small);)
{
if(l.first != s->first)
{
++s;
}
else
{
unique = false;
s = small.erase(s);
}
}
if(unique)
{
result.push_back(l.second);
}
}
for(const auto & s: small)
{
result.push_back(s.second);
}
return result;
}
Предлагаю более простой вариант - воспользоваться QSet
, контейнером, предоставляющим быстрый поиск и действия типа пересечения, сложения и вычитания:
QStringList MainWindow::diff(const QString &str1, const QString &str2)
{
QStringList list1 = str1.split(" ", QString::SkipEmptyParts);
QStringList list2 = str2.split(" ", QString::SkipEmptyParts);
QSet<QString> set1 = QSet<QString>::fromList(list1);
QSet<QString> set2 = QSet<QString>::fromList(list2);
QSet<QString> d = set2.subtract(set1);
return QStringList::fromSet(d);
}
На вашем примере
qDebug()<<diff("/dev/sda /dev/sda1 /dev/sdc /dev/sdc1",
"/dev/sda /dev/sda1 /dev/sdb /dev/sdb1 /dev/sdc /dev/sdc1");
Вывод:
("/dev/sdb1", "/dev/sdb")
UPD
По замечанию @Andrej Levkovitch - этот алгоритм действительно не вполне оптимален, можно его улучшить, например, написав собственный split
сразу в QSet
и возвращая не QStringList
a QSet
. Но повторюсь, частота использования этого участка кода и объем данных говорит о том, что скорее всего узким местом в программе он не будет и оптимизировать его преждевременно не стоит.
UPD 2
Не заметил комментария @vegorov под вопросом, мой код в точности реализует его идею вплоть до ответа по поводу скорости работы.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Вопрос инициирован ответом в топике: Как я могу управлять применением z-index? Hover отменяет z-index до завершения transitions
Коллеги, кто-то проходил квест по написанию синтаксиса INSERT #Temp EXEC dboTest_Proc @a = @a в MySQL? Это вообще возможно без предварительного создания таблицы...