Character count of regular expression in cells in MATLAB - regex

Earlier I got some help as to how to make a script that will extract hashtags from a list of tweets and put them into an array of cells.
I used this as my code, inside a for loop
hashtagCell{i} = regexp(textRead{i}, '#[A-z]*', 'match');
This works for what it is supposed to do, but now I'm trying to find the average character length of the hashtags, so I need to be able to add the character length of each hashtag pulled out by the above function and add them together. However, when I try to use the size() function, it just gives me the size of the cell instead of the size of the strings, which is what I want. I can't figure out how to do this.

For a single string it would be like this:
%# example string with hashtags.
MyText = 'this is a #text with #hashtag and also #another hashtag';
%# create the hashtagCell.
hashtagCell = regexp(MyText, '#[A-z]*', 'match');
%# compute the mean.
AverageLength = mean(cellfun(#(x) size(x,2), hashtagCell));

This should help (and it gets rid of any loops, other than, perhaps, the one used to create CellOfText):
%# Example cell array of tweets
CellOfText = {'Bah #humbug says #Mr scrooge'; 'No #presents for you'};
%# Get all hash tags
HTC = regexp(CellOfText, '#[A-z]*', 'match');
%# Get the average hash tag length, being careful to unnest HTC
AvgLength1 = mean(cellfun('length', [HTC{:}]));
DISCLAIMER: The inspiration for this method came from this excellent answer to a similar question. Thanks to #Andrey for that.

Related

Regex pattern for number or three letters

I need to sort a table field with different kind of values:
number from 0 to 999+
group of three letters like AAA, AAB, AAC, AAD, etc.
StupidTable.js enables me to add a custom alphanumeric data type, but i'm not able to define the regex pattern.
I tried this code:
$("table").stupidtable({
"alphanum":function(a,b){
console.log(a,b)
var pattern = "^[a-zA-Z0-9_.-]*$";
var re = new RegExp(pattern);
var aNum = re.exec(a).slice(1);
var bNum = re.exec(b).slice(1);
return parseInt(aNum,10) - parseInt(bNum,10);
}
})
but it doesnt work. You can check the issue on this page clicking on "nr" tab: Test
Try something like this:
const regexPattern = /^[\d\w]{3}/gm;
This pattern allows you to capture a string if it contains only a 3 digit number or a 3 letter code. If you want to capture 0 and not 000, you will need to change {3} with {1,3}, but this will also capture A instead of AAA.
You might also consider normalizing your data in some ways, e.g. converting A to AAA and 0 to 000. This could be helpful for a number of reasons assuming your variable type is a string and not actually a number type. Does that make sense?
You can see how I've created this pattern at the link below, and try some tweaks to make it work well for you. I use this tool a lot and it will also generate some code for you in different languages. Good luck with your project, let me know how it goes.
Regex101.com

Extract a list of unique text characters/ emojis from a cell

I have a text in cell (A1) like this:
✌😋👅👅☝️😉🍌🍪💧💧
I want to extract the unique emojis from this cell into separate cells:
✌😋👅☝️😉🍌🍪💧
Is this possible?
You want to put each character of ✌😋👅👅☝️😉🍌🍪💧💧 to each cell by splitting using the built-in function of Google Spreadsheet.
Sample formula:
=SPLIT(REGEXREPLACE(A1,"(.)","$1#"),"#")
✌😋👅👅☝️😉🍌🍪💧💧 is put in a cell "A1".
Using REGEXREPLACE, # is put to between each character like ✌#😋#👅#👅#☝#️#😉#🍌#🍪#💧#💧#.
Using SPLIT, the value is splitted with #.
Result:
Note:
In your question, the value of ️ which cannot be displayed is included. It's \ufe0f. So "G1" can be seen like no value. But the value is existing. So please be careful this. If you want to remove the value, you can use ✌😋👅👅☝😉🍌🍪💧💧.
References:
REGEXREPLACE
SPLIT
Added:
From marikamitsos's comment, I could notice that my understanding was not correct. So the final result is as follows. This is from marikamitsos.
=TRANSPOSE(UNIQUE(TRANSPOSE(SPLIT(REGEXREPLACE(A1,"(.)","$1#"),"#"))))
or try:
=TRANSPOSE(UNIQUE(TRANSPOSE(REGEXEXTRACT(A1, REPT("(.)", LEN(A1))))))
Formula
Appears, one of the best formula solutions would be:
=SPLIT(REGEXREPLACE(A1,"(.)","$1#"),"#")
You may also add some additional checks like skin tones & intermediate chars:
=TRANSPOSE(SPLIT(REGEXREPLACE(A2,"(.[🏻🏼🏽🏾🏿"&CHAR(8205)&CHAR(65039)&"]*)","#$1"),"#"))
It will help to join some emojis as a single emoji.
Script
More precise way is to use the script:
https://github.com/orling/grapheme-splitter/blob/master/index.js
↑
Add the code to Script editor
Add code for sample usage:
function splitEmojis(string) {
var splitter = new GraphemeSplitter();
// split the string to an array of grapheme clusters (one string each)
var graphemes = splitter.splitGraphemes(string);
return graphemes;
}
Tests
Not 100% precise
1
Please note: some emojis are not correctly shown in sheets
🏴󠁧󠁢󠁷󠁬󠁳󠁿🏴󠁧󠁢󠁳󠁣󠁴󠁿🏴󠁧󠁢󠁥󠁮󠁧󠁿🏴
↑ emojis:
flag: England
flag: Scotland
flag: Wales
black flag
are the same for Google Sheets.
2
Vlookup function in #GoogleSheets and in #Excel thinks chars
#️⃣ and
*️⃣
are the same!

Split string and get last element

Let's say I have a column which has values like:
foo/bar
chunky/bacon/flavor
/baz/quz/qux/bax
I.e. a variable number of strings separated by /.
In another column I want to get the last element from each of these strings, after they have been split on /. So, that column would have:
bar
flavor
bax
I can't figure this out. I can split on / and get an array, and I can see the function INDEX to get a specific numbered indexed element from the array, but can't find a way to say "the last element" in this function.
Edit:
this one is simplier:
=REGEXEXTRACT(A1,"[^/]+$")
You could use this formula:
=REGEXEXTRACT(A1,"(?:.*/)(.*)$")
And also possible to use it as ArrayFormula:
=ARRAYFORMULA(REGEXEXTRACT(A1:A3,"(?:.*/)(.*)$"))
Here's some more info:
the RegExExtract function
Some good examples of syntax
my personal list of Regex Tricks
This formula will do the same:
=INDEX(SPLIT(A1,"/"),LEN(A1)-len(SUBSTITUTE(A1,"/","")))
But it takes A1 three times, which is not prefferable.
You could do this too
=index(SPLIT(A1, "/"), COLUMNS(SPLIT(A1, "/"))-1)
Also possible, perhaps best on a copy, with Find:
.+/
(Replace with blank) and Search using regular expressions ticked.
You can try use this!
You've got the array of String, so you can acess the last element by length
String message = "chunky/bacon/flavor";
String[] outSplited = message.split("/");
System.out.println(outSplited[outSplited.length -1]);

Postgresql - How do I extract the first occurence of a substring in a string using a regular expression pattern?

I am trying to extract a substring from a text column using a regular expression, but in some cases, there are multiple instances of that substring in the string.
In those cases, I am finding that the query does not return the first occurrence of the substring. Does anyone know what I am doing wrong?
For example:
If I have this data:
create table data1
(full_text text, name text);
insert into data1 (full_text)
values ('I 56, donkey, moon, I 92')
I am using
UPDATE data1
SET name = substring(full_text from '%#"I ([0-9]{1,3})#"%' for '#')
and I want to get 'I 56' not 'I 92'
You can use regexp_matches() instead:
update data1
set full_text = (regexp_matches(full_text, 'I [0-9]{1,3}'))[1];
As no additional flag is passed, regexp_matches() only returns the first match - but it returns an array so you need to pick the first (and only) element from the result (that's the [1] part)
It is probably a good idea to limit the update to only rows that would match the regex in the first place:
update data1
set full_text = (regexp_matches(full_text, 'I [0-9]{1,3}'))[1]
where full_text ~ 'I [0-9]{1,3}'
Try the following expression. It will return the first occurrence:
SUBSTRING(full_text, 'I [0-9]{1,3}')
You can use regexp_match() In PostgreSQL 10+
select regexp_match('I 56, donkey, moon, I 92', 'I [0-9]{1,3}');
Quote from documentation:
In most cases regexp_matches() should be used with the g flag, since
if you only want the first match, it's easier and more efficient to
use regexp_match(). However, regexp_match() only exists in PostgreSQL
version 10 and up. When working in older versions, a common trick is
to place a regexp_matches() call in a sub-select...

Regex Split: Split column into Name, percentage andsolvent

Looking for a regex that can split expressions like:
A-6-b 10/%XYZ
into:
A-6-b
10%
/XYZ
Note that the first group can also contain spaces and numbers:
AQDF 100 56%/ABC
and percentage can be a float:
SFSDF 0.1%/ABC
I've come up with (^[A-Z\s\d-]*)(?!%)(\d+%)(.*$) but this doe snot match any percentages that are floats and more importantly even simple examples like ABC 10%/XYZ fail because the first digit of the percentage is assigned to the first capturing group.
Any idea how I can achieve what I want? I'm not a regex expert...
EDIT: fixed errors in example
EDIT2:
The examples are not complete. Here one more:
ABC Dwsd 0.01%/XYZ QST
First part can contain spaces
Last Part can contain spaces
number can be a float
Super simple:
/^(.*) ([1-9][0-9]*(?:\.[0-9]+)?%)(.*)$/
The most easily identifiable item is your percentage, so the ([1-9][0-9]*(?:\.[0-9]+)?%) part deals with finding that.
Then it's simply a case of getting everything before (excluding the final space) to get the name, and everything after to get the solvent.
Done.
Don't overcomplicate this by using one unreadable regex.
Based on what you've said, your separators are well defined (the last space and the last %). In JavaScript, for example, you could use:
var str = "A-6-b 10/%XYZ";
var firstSeparator = str.lastIndexOf(' ');
var secondSeparator = str.lastIndexOf('%');
var name = str.substring(0, firstSeparator);
var percentage = str.substring(firstSeparator + 1, secondSeparator + 1); // we want to include the % separator in this one
var solvent = str.substring(secondSeparator + 1);
console.log(name, percentage, solvent);
Working JSFiddle: http://jsfiddle.net/rL5uymhm/
(There may be a typo in your question, as your examples differ on where the / symbol appears. So the code may need tweaking. My point still stands – don't use a regex for the sake of it when there is a more readable alternative.)
IF you really want to use a regex, /^(.+ )([^%]+%)(.*)$/ should work.
I try this Let me know if you have any problem in comment.
((?:(?!\s*[0-9]*\/%).)*)\s*([\d\/%]*)\s*(.*)
SEE DEMO : http://regex101.com/r/lL8oN4/1
This one works for me (using PCRE):
/^(.+) ([0-9.]+)[\/%]+([^\/]+)$/