I'm working with DNA, RNA and protein sequences and QRegExp doesn't work for me to detect if
the sequence contains only certain characters.
For example unambiguous contains only acgt :
seq.contains(QRegExp("[gatc]"))
Doesn't work for me. How can I correct that ?
You're looking for whether the sequence contains characters other than gatc. You also shouldn't be using the deprecated QRegExp in Qt 5. So:
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
QRegularExpression invalid("[^gatcGATC]");
#else
QRegExp invalid("[^gatcGATC]");
#endif
if (seq.contains(invalid)) {
qDebug() << "invalid sequence!";
...
}
by default QRegExp is case sensitive.
QRegExp ( const QString & pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive
You should add the parameter to make it case insensitive.
Misunderstanding the OP request. This solution is for finding subsequences only containing all 4 elements once.
Since regular expressions cannot count occurrences, you will need to check for any possible match. Short example using 2 chars: AB and BA. AAABBBAAA to be checked. You will need to use QRegExp("(AB|BA)") since the expression cannot search for permutation. So looking for sequences having every element once, requires to have the regex check for (ACGT|ACTG|AGCT|....)
It would be easier to implement something like:
QString seq = "gactacgtccttacgaccaacggcgataaaaattgcccgcataagacaactttcgaggcg";
QMap<QChar,int> count;
void resetCounter()
{
count[QChar('a')] = 0;
count[QChar('c')] = 0;
count[QChar('g')] = 0;
count[QChar('t')] = 0;
}
bool checkCounter()
{
foreach(count.values(), int val)
if(val != 1)
return false;
return true;
}
resetCounter();
for(int i=0; i<seq.length(); i++)
{
count[seq.at(i)] = count[seq.at(i)] + 1;
if(count[seq.at(i)] > 1)
{
resetCounter();
count[seq.at(i)] = 1;
}
if(checkCounter())
{
//Found sequence
count[seq.at(i-3)] = 0;
}
}
Edit: Found small mistake. Have to set current element to 1 after resetCounter() being called
Related
I have the following QString:
QString funcProxy = "executeProxy(\"%1\", \"%2\", \"%3\")";
The data for each on is in:
QList<QString> listProxy;
How would I go about adding the data in listProxy to funcProxy using the arg() method?
funcProxy.arg(??);
Thanks
Regarding the answer from #owacoder, you do not actually need the replace function, the following should work correclty:
for (int i = 0; i < listProxy.size(); ++i) {
funcProxy = funcProxy.arg(listProxy.at(i));
}
Why you ask: From the documentation on QString::arg()
Returns a copy of this string with the lowest numbered place marker replaced by string
Thus it replaces the lowest number with the string in the arg call. First iteration contains %1, %2 and %3, so it replaces %1. Next iteration contains %2 and %3, thus replaces %2.
Alternatively if you have control over funcProxy you can do the following given you can change your list to a QStringList:
QString funcProxy = "executeProxy(\"%1\")";
QStringList listProxy{"a", "b", "c"};
funcProxy = funcProxy.arg(listProxy.join("\", \""));
If you know you'll have exactly 3 elements in your list, you can do this:
funcProxy.arg(listProxy.at(0)).arg(listProxy.at(1)).arg(listProxy.at(2));
Otherwise, you could use this:
for (int i = 0; i < listProxy.size(); ++i)
funcProxy.replace(QString("%%1").arg(i+1), listProxy.at(i));
I wrote a function to convert a hexa string representation (like x00) of some binary data to the data itself.
How to improve this code?
QByteArray restoreData(const QByteArray &data, const QString prepender = "x")
{
QByteArray restoredData = data;
return QByteArray::fromHex(restoredData.replace(prepender, ""));
}
How to improve this code?
Benchmark before optimizing this. Do not do premature optimization.
Beyond the main point: Why would you like to optimize it?
1) If you are really that concerned about performance where this negligible code from performance point of view matters, you would not use Qt in the first place because Qt is inherently slow compared to a well-optimized framework.
2) If you are not that concerned about performance, then you should keep the readability and maintenance in mind as leading principle, in which case your code is fine.
You have not shown any real world example either why exactly you want to optimize. This feels like an academic question without much pratical use to me. It would be interesting to know more about the motivation.
That being said, several improvement items, which are also optimization, could be done in your code, but then again: it is not done for optimization, but more like logical reasons.
1) Prepender is bad name; it is usually called "prefix" in the English language.
2) You wish to use QChar as opposed to QString for a character.
3) Similarly, for the replacement, you wish to use '' rather than the string'ish "" formula.
4) I would pass classes like that with reference as opposed to value semantics even if it is CoW (implicitly shared).
5) I would not even use an argument here for the prefix since it is always the same, so it does not really fit the definition of variable.
6) It is needless to create an interim variable explicitly.
7) Make the function inline.
Therefore, you would be writing something like this:
QByteArray restoreData(QByteArray data)
{
return QByteArray::fromHex(data.replace('x', ''));
}
Your code has a performance problem because of replace(). Replace itself is not very fast, and creating intermediate QByteArray object slows the code down even more. If you are really concerned about performance, you can copy QByteArray::fromHex implementation from Qt sources and modify it for your needs. Luckily, its implementation is quite self-contained. I only changed / 2 to / 3 and added --i line to skip "x" characters.
QByteArray myFromHex(const QByteArray &hexEncoded)
{
QByteArray res((hexEncoded.size() + 1)/ 3, Qt::Uninitialized);
uchar *result = (uchar *)res.data() + res.size();
bool odd_digit = true;
for (int i = hexEncoded.size() - 1; i >= 0; --i) {
int ch = hexEncoded.at(i);
int tmp;
if (ch >= '0' && ch <= '9')
tmp = ch - '0';
else if (ch >= 'a' && ch <= 'f')
tmp = ch - 'a' + 10;
else if (ch >= 'A' && ch <= 'F')
tmp = ch - 'A' + 10;
else
continue;
if (odd_digit) {
--result;
*result = tmp;
odd_digit = false;
} else {
*result |= tmp << 4;
odd_digit = true;
--i;
}
}
res.remove(0, result - (const uchar *)res.constData());
return res;
}
Test:
qDebug() << QByteArray::fromHex("54455354"); // => "TEST"
qDebug() << myFromHex("x54x45x53x54"); // => "TEST"
This code can behave unexpectedly when hexEncoded is malformed (.e.g. "x54x45x5" will be converted to "TU"). You can fix this somehow if it's a problem.
I tried this code but still have problem for QString to short value for example it work well for text = 20 but it return 0 for value = 20.5.
but I need value=20. how can I solve it?
inline __int16 GetStaticToInteger(QLineEdit* lineEdit) {
QString text; __int16 nValue = 0;
nValue = QString::number(lineEdit->text().toDouble()).toShort();
return nValue;
}
'20.5' is not a valid text representation for an integer value. You can check this:
QString str("20.5");
bool ok;
short s = str.toShort(&ok);
qDebug() << ok
The output will be 'false'.
If you need an integer value you can do this:
short s = str.toDouble();
If you need your value rounded to the nearest integer use qRound:
short s = qRound(str.toDouble());
You have made it to complicated.
inline __int16 GetInteger16FromStatic(QLineEdit* lineEdit) {
QString text; __int16 nValue = qRound(lineEdit->text().toDouble());
return nValue;
}
Also Qt provides types with defined size, like qint16 to be compiler/platform independent, so you don't have to use __int16.
The function gets an integer and a digit, and should return true
if the digit appears an even number of times in the integer, or false if not.
For example:
If digit=1 and num=1125
the function should return true.
If digit=1 and num=1234
the function should return false.
bool isEven(int num, int dig)
{
bool even;
if (num < 10)
even = false;
else
{
even = isEven(num/10,dig);
This is what I've got so far, and I'm stuck...
This is homework so please don't write the answer but hint me and help me get to it by myself.
To set up recursion, you need to figure out two things:
The base case. What is are the easy cases that you can handle outright? For example, can you handle single-digit numbers easily?
The rule(s) that reduce all other cases towards the base case. For example, can you chop off the last digit and somehow transform the solution for the remaning partial number into the solution for the full number?
I can see from your code that you've made some progress on both of these points. However, both are incomplete. For one thing, you are never using the target digit in your code.
The expression num%10 will give you the last digit of a number, which should help.
Your base case is incorrect because a single digit can have an even number of matches (zero is an even number). Your recursive case also needs work because you need to invert the answer for each match.
This funtion isEven() takes a single integer and returns the true if the number of occurence of numberToCheck is even.
You can change the base as well as the numberToCheck which are defined globally.
#include <iostream>
using std::cout;
using std::endl;
// using 10 due to decimal [change it to respective base]
const int base = 10;
const int numberToCheck = 5;
//Checks if the number of occurence of "numberToCheck" are even or odd
bool isEven(int n)
{
if (n == 0)
return 1;
bool hasNumber = false;
int currentDigit = n % base;
n /= base;
if (currentDigit == numberToCheck)
hasNumber = true;
bool flag = isEven(n);
// XOR GATE
return ((!hasNumber) && (flag) || (hasNumber) && (!flag));
};
int main(void)
{
// This is the input to the funtion IsEven()
int n = 51515;
if (isEven(n))
cout << "Even";
else
cout << "Odd";
return 0;
}
Using XOR Logic to integrate all returns
// XOR GATE
return ((!hasNumber) && (flag) || (hasNumber) && (!flag));
I have a QTableWidget and the first column contains numbers from 1 to 1000. Now I need to sort the table based on this first column.
I'm using the function sortItems(int column, Qt::AscendingOrder), but it is displayed as:
1, 10, 100, 1000, 101, 102, ...
Yet I need this result:
1, 2, 3 ,4...., 1000.
I'm using a CSV file for populating the table.
The values are sorted as strings because you stored them as such in the model.
The QVariant can remember the original type of the data if you let it do the conversion itself, and the comparison operator from that type will be used when sorting:
// Get the value from the CSV file as a numeric type
int valueFromCsvFile = ...;
// don't do this
QTableWidgetItem *item = new QTableWidgetItem(QString::number(valueFromCsvFile));
// but do this instead
QTableWidgetItem *item = new QTableWidgetItem;
item.setData(Qt::EditRole, valueFromCsvFile);
The cell editor will also adapt to the type of the QVariant:
QSpinBox for int,
QDoubleSpinBox for double and float,
QDateTimeEdit for QDateTime
...
The easiest way is probably to subclass QTableWidgetItem and then implement the < operator to be smart about the fact that you're sorting numbers and not strings.
class MyTableWidgetItem : public QTableWidgetItem {
public:
bool operator <(const QTableWidgetItem &other) const
{
return text().toInt() < other.text().toInt();
}
};
Then when you're populating your table you can pass it instances of your custom items that know how to sort themselves properly instead of the generic ones.
One way that worked in my situation was
1) before filling the table, turn off sorting:
table.setSortingEnabled(False)
2) pad the number strings with blanks and make all strings in the column have the same length:
(' '+numStr)[-4:]
3) after filling the table, turn on sorting:
table.setSortingEnabled(True)
This fixed the row sorting problem and the numerical order.
I don't know if the accepted answer used to work, but with Qt5.1, it doesn't.
In order to work, the operator< definition has to match the virtual definition from qtablewidget.h.
Another interesting addition is to sort items that have numbers, but start with a currency sign ($ or € for instance) or end with %.
Here is the updated code:
class TableNumberItem : public QTableWidgetItem
{
public:
TableNumberItem(const QString txt = QString("0"))
:QTableWidgetItem(txt)
{
}
bool operator < (const QTableWidgetItem &other) const
{
QString str1 = text();
QString str2 = other.text();
if (str1[0] == '$' || str1[0] == '€') {
str1.remove(0, 1);
str2.remove(0, 1); // we assume both items have the same format
}
if (str1[str1.length() - 1] == '%') {
str1.chop(1);
str2.chop(1); // this works for "N%" and for "N %" formatted strings
}
double f1 = str1.toDouble();
double f2 = str2.toDouble();
return str1.toDouble() < str2.toDouble();
}
};
Then, you add the items that contain numbers using something like this:
myTableWidget->setItem(row, col, new TableNumberItem("$0"));
Note that this class must be used with numbers only, it will not sort strings correctly (as is also the case with the accepted answer).
I had same problem and the The answer of #Chris worked for me!
but a little modification is need. I can't comment. so I write here.
class MyTableWidgetItem : public QTableWidgetItem {
public:
bool operator <(const QTableWidgetItem &other) const
{
if (text()=="")
return text().toDouble() > other.text().toDouble();
else
return text().toDouble() < other.text().toDouble();
}
};