Convert a StringBuilder to a Jagged Array - vb.net

I have built a VB.Net class that will be used in VBA for reading text files. I've set it up so the user can specify what tables in the file he wants to return. What I have done is build a StringBuilder of the tables, then return it as a jagged array, but I can't quite get the conversion of the builder to array part right. I'd like the the first level to be split on "NewLine" and the second level to be split on ",".
Is this possible without having to use multiple arrays and\or loops?

This will create the jagged array:
Dim myArray = (From row In myStringBuilder.ToString().Split({vbCrLf}, StringSplitOptions.None)
Select (From col In row.Split(","c)
Select col
).ToArray()
).ToArray()
Explanation:
First, we convert the StringBuilder to a String: myStringBuilder.ToString()
Then we split on line breaks: Split({vbCrLf}, StringSplitOptions.None). Since a line break consists of two characters in Windows, we use the Split overload that accepts a string array (hence the braces).
Within the row we split the line on commas: Split(","c). The c specifies that this is a character instead of a string.
Finally, we convert this enumerable of enumerables into an array of arrays by applying ToArray to the outer as well as the inner LINQ expression.

You could represent your jagged array using nested lists and generics. The outer (row) would be a generic list and the inner (col) could be a list of strings.
Other approaches could leverage XML or LINQ but would be less efficient.

Related

Convert String to array and validate size on Vertica

I need to execute a SQL query, which converts a String column to a Array and then validate the size of that array
I was able to do it easily with postgresql:
e.g.
select
cardinality(string_to_array('a$b','$')),
cardinality(string_to_array('a$b$','$')),
cardinality(string_to_array('a$b$$$$$','$')),
But for some reason trying to convert String on vertica to array is not that simple, Saw this links:
https://www.vertica.com/blog/vertica-quick-tip-dynamically-split-string/
https://forum.vertica.com/discussion/239031/how-to-create-an-array-in-vertica
And much more that non of them helped.
I also tried using:
select REGEXP_COUNT('a$b$$$$$','$')
But i get an incorrect value - 1.
How can i Convert String to array on Vertica and gets his Length ?
$ has a special meaning in a regular expression. It represents the end of the string.
Try escaping it:
select REGEXP_COUNT('a$b$$$$$', '[$]')
You could create a UDx scalar function (UDSF) in Java, C++, R or Python. The input would be a string and the output would be an integer. https://www.vertica.com/docs/9.2.x/HTML/Content/Authoring/ExtendingVertica/UDx/ScalarFunctions/ScalarFunctions.htm
This will allow you to use language specific array logic on the strings passed in. For example in python, you could include this logic:
input_list = input.split("$")
filtered_input_list = list(filter(None, input_list))
list_count = len(filtered_input_list)
These examples are a good starting point for writing UDx's for Vertica. https://github.com/vertica/UDx-Examples
I wasn't able to convert to an array - but Im able to get the length of the values
What i do is convert to Rows an use count - its not best performance wise
But with this way Im able to do also manipulation like filtering of each value between delimiter - and i dont need to use [] for characters like $
select (select count(1)
from (select StringTokenizerDelim('a$b$c','$') over ()) t)
Return 3

Find records where length of array equal to - Rails 4

In my Room model, I have an attribute named available_days, which is being stored as an array.
For example:
Room.first.available_days
=> ["wed", "thurs", "fri"]
What is the best way to find all Rooms where the size of the array is equal to 3?
I've tried something like
Room.where('LENGTH(available_days) = ?', 3)
with no success.
Update: the data type for available_days is a string, but in order to store an array, I am serializing the attribute from my model:
app/models/room.rb
serialize :available_days
Can't think of a purely sql way of doing it for sqlite since available_days is a string.
But here's one way of doing it without loading all records at once.
rooms = []
Room.in_batches(of: 10).each_record do |r|
rooms << r if r.available_days.length == 3
end
p rooms
If you're using postgres you can parse the serialized string to an array type, then query on the length of the array. I expect other databases may have similar approaches. How to do this depends on how the text is being serialized, but by default for Rails 4 should be YAML, so I expect you data is encoded like this:
---
- first
- second
The following SQL will remove the leading ---\n- as well as the final newline, then split the remaining string on - into an array. It's not strictly necessary to cleanup the extra characters to find the length, but if you want to do other operations you may find it useful to have a cleaned up array (no leading characters or trailing newline). This will only work for simple YAML arrays and simple strings.
Room.where("ARRAY_LENGTH(STRING_TO_ARRAY(RTRIM(REPLACE(available_days,'---\n- ',''),'\n'), '\n- '), 1) = ?", 3)
As you can see, this approach is rather complex. If possible you may want to add a new structured column (array or jsonb) and migrate the serialized string into the a typed column to make this easier and more performant. Rails supports jsonb serialization for postgres.

How to convert in hive a string representation of array of json objects back to array form

I am working in hive / SQL. I have a column in my table with strings which represent an array of json objects. I need to convert the strings to arrays of JSON strings.
For example, I have this,
"[{a:1, b:1},{a:2, b:2}]"
And I want to get this:
["{a:1, b:1}","{a:2, b:2}"]
Tried casting the string as array but that didn't work. Any ideas on how do this in a smart way short of splitting by "},{"?
never mind, I ended up just splitting the string on "}" and then adding back the "}" to each piece, worked well!

Weird results when splitting strings in VB.NET

I was getting weird results when doing multiple splits on a string, so I decided to make a simple test to figure out what was going on
testString "1234567891011121314151617181920"
If I wanted to get whats between 10 to 20 in Javascript I would do this:
var results = testString.split("10")[1].split("20")[0]
Which would return 111213141516171819
However when I do this in VB I get 111
Split(testString,"10")(1).Split("20")(0)
It seems the 2nd split is only recognizing the first character no matter what I put.
So it's stopping when it finds the next "2" in the string, even "2abc" would have the same outcome even though that string doesn't even exist.
String.Split does not have an overload that takes only a String. The argument is a Char array or String array. Your string is probably being converted to a char array. Explicitly pass a string array like so:
testString.Split(New String() { "10" }, StringSplitOptions.None)
Try wrapping the second split so it's fashioned like the first one, i.e.:
Split( Split(testString,"10")(1), "20" )(0)"
Vb treats the delimiter argument only as a single character.
This is a tricky scenario that I have seen trip people up before, so I think it is worth a little more explanation than the other answers give. In your original format Split(testString,"10")(1).Split("20")(0), you are unknowingly using two DIFFERENT Split functions.
The first Split(testString,"10") is using the Microsoft.VisualBasic.Strings.Split function, which takes String type parameters. http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.strings.split(v=vs.110).aspx
The second .Split("20")(0) is using System.String.Split method, which does not have an overload that takes a String parameter. http://msdn.microsoft.com/en-us/library/System.String.Split(v=vs.110).aspx
So what was happening is:
Split(testString,"10") uses Microsoft.VisualBasic.Strings.Split, which
returns new String() {"123456789", "11121314151617181920"}
(1) means get 1st position of the returned array, which is "11121314151617181920"
"11121314151617181920".Split("20")(0) uses System.String.Split, and attempts to split on string separator "20"
NOTE: The string "20" param gets implicitly converted to a char "2" because the only single parameter overload of String.Split has a signature of Public Function Split (ParamArray separator As Char()) As String(). The ParamArray parameter option allows you to pass a comma delimited list of values into the function, similar to how String.Format works with a dynamic # of replacement values. http://msdn.microsoft.com/en-us/library/538f81ec.aspx
Step 3 code becomes "11121314151617181920".Split(new Char() {CChar("20")})(0), which using literal values is "11121314151617181920".Split(new Char() {"2"c})(0). The result is {"111", "13141516171819", "0"}. Get the 0th position, returns "111".
So to avoid confusion, you should convert your code to use the same version of Split on both sides.
Either of the 2 examples below should work:
Example 1: Using Microsoft.VisualBasic.Strings.Split:
Split( Split(testString,"10")(1), "20" )(0)
Example 2: Using System.String.Split:
testString _
.Split(New String() {"10"}, StringSplitOptions.None)(1) _
.Split(New String() {"20"}, StringSplitOptions.None)(0)

sorting and getting uniques

i have a string that looks like this
"apples,fish,oranges,bananas,fish"
i want to be able to sort this list and get only the uniques. how do i do it in vb.net? please provide code
A lot of your questions are quite basic, so rather than providing the code I'm going to provide the thought process and let you learn from implementing it.
Firstly, you have a string that contains multiple items separated by commas, so you're going to need to split the string at the commas to get a list. You can use String.Split for that.
You can then use some of the extension methods for IEnumerable<T> to filter and order the list. The ones to look at are Enumerable.Distinct and Enumerable.OrderBy. You can either write these as normal methods, or use Linq syntax.
If you need to get it back into a comma-separated string, then you'll need to re-join the strings using the String.Join method. Note that this needs an array so Enumerable.ToArray will be useful in conjunction.
You can do it using LINQ, like this:
Dim input = "apples,fish,oranges,bananas,fish"
Dim strings = input.Split(","c).Distinct().OrderBy(Function(s) s)
I'm not a VB.NET programmer, but I can give you a suggestion:
Split the string into an array
Create a second array
Cycle through the first array, adding any value that is not in the second.
Upon completion, your second array will have only unique values.