I'm trying to rate matches based on the number of words from the query that are found in the row. I stared doing this:
SELECT Text, MATCH(`Text`) AGAINST ('$s') AS Grade
But soon I realised this didn't work since Grade is based on a lot of stuff like for example the order the words are, each word's length and so on.
I only want to know the % of words that are present in a row.
EG:
$s = 'i want pizza'
`Text` = 'pizza I want' // In this case Grade should be 100 as all words are found
Other examples:
Text | Grade
pizza I want too | 100 // All words were found, It doesn't matter if there are extra words
pizza I want | 100
i want | 66 // Only 66% of the words are present
want want want | 33 // Only 33% of the words are present
$s = 'i want pizza';
$text = 'pizza I want';
//move to lower-case to ignore case-differences
$s = strtolower($s);
$text = strtolower($text);
//count the number of words in $s
$slen = count(explode(" ", $s));
//create an array of words from the text that we check
$arr = explode(" ", $text);
$count = 0;
//go over the words from $text and count words that appear on $s
foreach ($arr as $word) {
if(strpos($s, $word) !== false){
$count++;
}
}
//display the percentage in format XX.XX
echo number_format((double)(100 * $count/$slen),2);
Related
I have this table in normal string format ,
I want to convert this string to json object in PowerShell. ConvertTo-Json is not giving in correct format.
The answer depends somewhat on the true format of the table. If I assume this is tab delimited and that each column name doesn't have spaces I could pull it out something like:
$String =
#"
test test2 first others versions
------------------------------------------
Decimal 1 2 5 p
Decimal 1 3 8 p
Decimal 1 2 4 i
Decimal 2 2 6 p
Decimal 5 4 6 k
Decimal 2 5 2 p
"#
$String = $String -split "\r?\n"
$Headers = $String[0] -split "\s"
$Objects =
$String[2..($String.Count -1)] |
ConvertFrom-Csv -Header $Headers -Delimiter "`t" |
ConvertTo-Json
Above, -split the big string into lines, then look at the header line and -split it to get an array of column headers. Now skipping the first 2 elements in the $String array convert the remaining lines to objects using ConvertFrom-Csv and using the previously extracted $Headers array.
Note: This segment may also work and may be preferred for readability:
$Objects =
$String |
Select-Object -Skip 2 |
ConvertFrom-Csv -Header $Headers -Delimiter "`t" |
ConvertTo-Json
Note: Splitting on white space ( "\s" ) may cause issues if the field data may have whitespace itself.
However, given the ambiguity, a more certain approach might be more reliable, I would use the known start and end positions of the table's fields to do this.
Continuing with the above example string:
$String =
#"
test test2 first others versions
------------------------------------------
Decimal 1 2 5 p
Decimal 1 3 8 p
Decimal 1 2 4 i
Decimal 2 2 6 p
Decimal 5 4 6 k
Decimal 2 5 2 p
"#
$String = $String -Split "\r?\n"
$String |
Select-Object -Skip 2 |
ForEach-Object{
[PSCustomObject]#{
test = $_.SubString(0,7)
test2 = $_.SubString(8,1)
first = $_.SubString(14,1)
others = $_.SubString(20,1)
versions = $_.SubString(26,1)
}
}
Again, these positions may change depending if the columns are separated by spaces or tabs. My sample data may not be the same as yours and you may need to play with those positions. That said this is a very useful technique for deal with output from traditional console applications, very much worth knowing...
Note: Thanks Neko Nekoru; I added '?' to the RegEx to accommodate both Unix & Windows line ending styles.
I have a table that has 45 columns for tax values
| Tax1 | Tax2 | .......... | Tax 44 | Tax45 |
I read in a variable length positional record that can contain zero to 90 values. The record is structured so that the first 3 characters are the tax code (values 001 - 045) and the next 7 characters are the tax value:
Examples:
0010013.990140005.00
0040002.00
0150001.150320002.200410014.250420012.990430000.500440001.750450004.68
What I would like to do is, for each record:
if ISNULL(record) or LEN(record) < 10 (3 characters for the code, 7 characters for the value)
quit
else
determine the amount of 10 character sections
for each 10 character section
taxCode = SUBSTRING(record, 1, 3)
taxValue = SUBSTRING(record, 4, 10)
table.Tax(taxCode).Value = taxValue (ex: using the first example record, column Tax1 will hold a value of 0013.99, Tax14 will be 0005.00)
next section
all other Tax[n] columns will have a value of 0.00
end if
Is there a way to do this without having to create 45 variables, one for each corresponding column?
EDIT:
I apologize for the lack of clarity. I receive a flat file from our VMS database. This file has multiple record types per file (ie: IT01, IT02, IT03, IT04, IT05, IT06, IT07). Each record type is on its own line. I read this file into a staging table, which the record type from the data on the line. For example (this is the record type I am referring to in my question):
IT06404034001005.000031013.000
This gets loaded into my staging table as:
RecordType | RecordData |
------------------------------------------
IT06 | 404034001005.000031013.000
The RecordData field is then able to be broken down further as:
ItemNumber | RecordData |
-------------------------------------
404034 | 001005.000031013.000
With a little bit of up-front work, I was able to create a script task to do exactly as I needed it to.
Step 1: add a script component. set it up as a transformation
Step 2: define all of the output columns necessary (long and tedious task, but it worked)
Step 3: put the following code in the script
public override void Input0_ProcessInputRow(Input0Buffer Row){
int sizeOfDataSegment = 11; // size of single record to be parsed (item number/next price)
string recordDetail = Row.RecordDetail.ToString().Trim();
string itemNumber = recordDetail.Substring(0, 6);
//System.Windows.Forms.MessageBox.Show(String.Format("Record Detail: {0}", recordDetail));
// we need a record for every item number, regardless if there are taxes or not
Row.Company = Variables.strCompanyName;
Row.ItemNumber = itemNumber;
if (recordDetail.Length > 6){
string taxData = recordDetail.Substring(6);
if (string.IsNullOrEmpty(taxData)){
}
else{
if (taxData.Length % sizeOfDataSegment == 0){
int numberOfTaxes = taxData.Length / sizeOfDataSegment;
//System.Windows.Forms.MessageBox.Show(String.Format("Number of taxe codes: {0}", numberOfTaxes.ToString()));
int posTaxCode = 0;
for (int x = 0; x < numberOfTaxes; x++){
string taxCode = taxData.Substring(posTaxCode, 3);
string taxValue = taxData.Substring(posTaxCode + 3, 8);
string outputColumnName = "TaxOut" + Convert.ToInt32(taxCode).ToString();
//System.Windows.Forms.MessageBox.Show(String.Format("TaxCode: {0}" + Environment.NewLine + "TaxValue: {1}", taxCode, taxValue));
//using taxCode value (ie: 001), find and set the value for the corresponding table column (ie: Tax1)
//foreach (System.Reflection.PropertyInfo dataColumn in Row.GetType().GetProperties()){
foreach (System.Reflection.PropertyInfo dataColumn in Row.GetType().GetProperties()){
if (dataColumn.Name == outputColumnName){
if (Convert.ToDecimal(taxValue) < 0){
// taxValue is a negative number, and therefore a percentage value
taxValue = (Convert.ToDecimal(taxValue) * -1).ToString() + "%";
}
else{
// taxValue is a positive number, and therefore a dollar value
taxValue = "$" + Convert.ToDecimal(taxValue).ToString();
}
dataColumn.SetValue(Row, taxValue);
}
}
posTaxCode += sizeOfDataSegment;
}
}
else{
System.Windows.Forms.MessageBox.Show(String.Format("Invalid record length({0}): {1}", taxData.Length, taxData));
}
}
}
}
I've a problem in getting the value of the query $scholars for $lt = $scholars->lat.The result is empty array for dd($lt);
.Any help would be helpful to my school project.
database of Scholar
id lat lng scholar_birthday scholar_GPA
1 10.275667 123.8569163 1995-12-12 89
2 10.2572114 123.839243 2000-05-05 88
3 9.9545909 124.1368558 2002-05-05 89
4 10.1208564 124.8495005 2010-05-05 85
$scholars = (new Scholar)->newQuery()->select('*');
$scholars->whereBetween(DB::raw('TIMESTAMPDIFF(YEAR,scholars.scholar_birthday,CURDATE())'),array($ship_age_from,$ship_age_to));
$scholars->whereBetween(DB::raw('scholar_GPA'),array($ship_gpa_from,$ship_gpa_to));
$lt = $scholars->lat;
$lg = $scholars->lng;
$str = $lt.','.$lg;
$url = 'http://maps.googleapis.com/maps/api/geocode/json?latlng='.trim($lt).','.trim($lg).'&sensor=false';
$json = #file_get_contents($url);
$data=json_decode($json);
$status = $data->status;
$data->results[0]->formatted_address;
dd($lt);
$scholars = $scholars->get();
dd Result
Undefined property: Illuminate\Database\Eloquent\Builder::$lat
Two things,
when you use the newQuery() you will still need to get() the result like such
$scholars = (new Scholar)->newQuery()->select('*')->get();
This however will retrieve a collection and not a single result so you will need to loop over this.
foreach($scholars as $scholar){
$lt = $scholars->lat;
dd($lt);
}
I have a large MySQL table with sorted data. When I need to find a starting point, I perform a binary search to find the lower bound ID (auto increment). The only problem is once some data is deleted, I need to look at the first existing row with a lower ID if the ID given by the algorithm doesn't exist. How should I modify this code to achieve that?
$l = 1;
$h = $max; //SELECT MAX(id)
while ($h - $l > 1){
$m = ($h + $l) / 2;
$q = mysqli_query($db, "SELECT col FROM tab WHERE id=". floor($m));
$result = array();
while($result[] = mysqli_fetch_row($q)){;}
if ($result[0][0] < $val) $l = $m;
else $h = $m;
}
echo round($m);
For example I want to find which rows have the value of col greater than 12345 and the table has max ID 10000. I start by looking at row 5000, where the col = 9000, then 7500 (col = 13000), then 6250 has been deleted, so I start looking for the 1st existing row with ID < 6250 and I find that 6245 has col = 10500. Now I'm looking between IDs 6873 and 7500 etc.
The right way to do this
So you have a table like this:
| ID | col |
---------------
| 1 | 15 |
| 3 | 155 |
| 18 | 9231|
| 190 |14343|
| 500 |16888|
You can get find 14343 with the following query:
SELECT ID, col FROM the_table WHERE col>12345 LIMIT 1;
To make it faster, you'd need to add an index (index word is worth googling)
ALTER TABLE `the_table` ADD INDEX `col` (`col`);
After that mysql will create a tree structure internally and will be doing binary searches on it for you.
This will be working much faster as you'll avoid multiple network roundtrips + other per request expenses (query parsing, optimization, all the locks & mutexes, ...)
Answer to your question
I need to look at the first existing row with a lower ID
E.g. you'd like to get first row with an ID < than 300, you do this (limit is what makes the query return only 1 result):
SELECT col FROM the_table WHERE ID < 300 LIMIT 1;
Lets Suppose we have 251 Items in stock and we want to convert it into Boxes and single items.
How can we do that?
I want result like that E.g
50 boxes 1 item
Total Items # 251 items
items per box = 5
251/5 = 50.2
But result must be as 50 boxes and 1 item
You need to use integer division and the modulo operator. In pseudo-code:
Boxes = AllItems / BoxSize
LooseItems = AllItems mod BoxSize
I'm assuming AllItems and BoxSize are integer variables.
Use integer division for determining the number of items in a box and the remainder operator for determining the number of the remaining items. These operators are ubiquitous in nearly every programming language.
An idea of how this could look like in JavaScript:
...
var totalItems = 251;
var itemsPerBox = 5;
var noOfBoxes = Math.floor(totalItems / itemsPerBox); // = 50
var noOfItems = totalItems % itemsPerBox; // = 1
alert("Number of Boxes: " + noOfBoxes + ". Number of Items: " + noOfItems);
Python answer:
itemsPerBox = 5
totalItems = 251
leftover = totalItems % itemsPerBox
boxableItems = totalItems - leftover
numBoxes = boxableItems / itemsPerBox
numLeftOver = totalItems - boxableItems
print "numLeftOver = ",
print numLeftOver
print "numBoxes = ",
print numBoxes