Adding one to many data to Lucene Index - asp.net

I am new to Lucene. I am trying to create an index of records. So far, I have just been adding one-to-one data to my index, and this seems fine. But, I have scenarios where I need to add one to many relationship data, and I am not sure what is the best way to handle this. I have tried adding each of the individual relationship, concacting feilds into CSV values, adding the field multiple times, but nothing seems to work. Here is my code for when the data is indexed:
Private Shared Sub _addToLuceneIndex(ByVal sampleData As LuceneSearchData, ByVal writer As IndexWriter)
Dim searchQuery = New TermQuery(New Term("Id", sampleData.Id.ToString()))
writer.DeleteDocuments(searchQuery)
Dim doc = New Document()
doc.Add(New Field("Id", sampleData.Id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED))
doc.Add(New Field("Name", sampleData.Name, Field.Store.YES, Field.Index.ANALYZED))
doc.Add(New Field("Description", sampleData.Description, Field.Store.YES, Field.Index.ANALYZED))
For Each item As Integer In sampleData.HomeStates
doc.Add(New Field("Home_State", item, Field.Store.YES, Field.Index.ANALYZED))
Next
'i have also tried
'doc.Add(New Field("HomeStates ", String.Join(",", sampleData.HomeStates ), Field.Store.YES, Field.Index.ANALYZED))
writer.AddDocument(doc)
End Sub
While the above code seems to index the one-to-one data, it does not for the HomeStates list of integers. Do I have to add the same document for every item in the list of integers? If so, how do you best manage this? I have several "one-to-many" relationships I need to include. I can see this getting unwieldy quickly. Or, is there a better way?
EDIT
I updated to add the one to may value as a field like this:
doc.Add(New Field("Geo_Locations", String.Join(" ", sampleData.Geo_Location), Field.Store.YES, Field.Index.ANALYZED))
This is how I search for that field:
Private Shared Function _search(ByVal searchQuery As String, ByVal Optional searchField As String = "") As IEnumerable(Of LuceneSearchData)
If String.IsNullOrEmpty(searchQuery.Replace("*", "").Replace("?", "")) Then Return New List(Of LuceneSearchData)()
Using searcher = New IndexSearcher(_directory, False)
Dim hits_limit = 1000
Dim analyzer = New StandardAnalyzer(Version.LUCENE_30)
If Not String.IsNullOrEmpty(searchField) Then
Dim parser = New QueryParser(Version.LUCENE_30, searchField, analyzer)
Dim query = parseQuery(searchQuery, parser)
Dim hits = searcher.Search(query, hits_limit).ScoreDocs
Dim results = _mapLuceneToDataList(hits, searcher)
analyzer.Close()
searcher.Dispose()
Return results
End If
End Using
End Function
Private Shared Function _mapLuceneToDataList(ByVal hits As IEnumerable(Of ScoreDoc), ByVal searcher As IndexSearcher) As IEnumerable(Of LuceneSearchData)
Dim listOfResults As List(Of LuceneSearchData)
Try
listOfResults = hits.[Select](Function(hit) _mapLuceneDocumentToData(searcher.Doc(hit.Doc))).ToList()
Catch ex As Exception
Return Nothing
End Try
Return listOfResults
End Function
Private Shared Function _mapLuceneDocumentToData(ByVal doc As Document) As LuceneSearchData
Return New LuceneSearchData With {
.Id = Convert.ToInt32(doc.[Get]("Id")),
.Mechanism_Name = doc.[Get]("Name"),
.Mechanism_Purpose = doc.[Get]("Description"),
.Geo_Location = doc.[Get]("Home_State")
}
End Function
I then call the search bu:
LuceneData = LuceneSearch.Search("5451", "HomeStates")

Creating a new document for each item will result in duplicates when searching for other fields.
You should design your documents & fields according to your needs.
If you don't need to search for these fields, store them as you wish.
If you need to search these multiple valued fields then create a field that can be searched for each item.
For integer lists you can merge them with spaces.
For string lists you should replace white spaces with some custom character while indexing and searching to avoid matching substrings (eg "stack overflow" => stack_overflow)

One to many using a term
As you have figured out, integers can be concatenated using a variety of separators including spaces, resulting in something like:
"234 12342 345 5476456 234"
The StandardAnalyzer will tokenise the above string into separate tokens just as it would any other string of words. So you can search them and it will give you the expected results.
One to many using a phrase
If you need to tokenise phrases, such as:
"Control Support Engineer|Technical Support Engineer|Maintenance Technician"
into individual phrases, not down to words (terms), then you'll need to inherit from a few classes. A tokenizer that inherits from CharTokenizer and an analyzer that inherits from Analyzer.
Tokenizer
public sealed class PipeTokenizer: CharTokenizer
{
public PipeTokenizer(LuceneVersion matchVersion, TextReader input) :
base(matchVersion, input)
{
}
public PipeTokenizer(LuceneVersion matchVersion, AttributeFactory factory, TextReader input) :
base(matchVersion, factory, input)
{
}
protected override bool IsTokenChar(int c)
{
return !((char)c).Equals('|'); //<-- the only line that matters
}
}
Pretty simple stuff so far.
Analyzer
public class PipeAnalyzer: Analyzer
{
protected override TokenStreamComponents CreateComponents(string fieldName, TextReader reader)
{
var tokenizer = new PipeTokenizer(LuceneVersion.LUCENE_48, reader);
var lowerCaseFilter = new LowerCaseFilter(LuceneVersion.LUCENE_48, tokenizer);
return new TokenStreamComponents(tokenizer, lowerCaseFilter);
}
}
This is based on what the KeywordAnalyzer does but with a twist. The KeywordAnalyzer is very simple. It takes the entire string, or phrase, and indexes it as is. No further breaking down into smaller tokens. The analyzer above uses the PipeTokenizer to break phrases down by the | separator, and converts to lower case.
Querying with any of the following phrases will return the doc:
"control support engineer"
"technical support engineer"
"maintenance technician"

Related

Declaring static list of strings and accessing by names [duplicate]

I am using Window Application for my project. There is situation where i need to define string enum and using it in my project.
i.e.
Dim PersonalInfo As String = "Personal Info"
Dim Contanct As String = "Personal Contanct"
Public Enum Test
PersonalInfo
Contanct
End Enum
Now i want value of that variable PersonalInfo and Contract as "Personal Info" and "Personal Contanct".
How can i get this value using ENUM? or anyother way to do it.
Thanks in advance...
For non-integer values, Const in a Structure (or Class) can be used instead:
Structure Test
Const PersonalInfo = "Personal Info"
Const Contanct = "Personal Contanct"
End Structure
or in a Module for direct access without the Test. part:
Module Test
Public Const PersonalInfo = "Personal Info"
Public Const Contanct = "Personal Contanct"
End Module
In some cases, the variable name can be used as a value:
Enum Test
Personal_Info
Personal_Contanct
End Enum
Dim PersonalInfo As String = Test.Personal_Info.ToString.Replace("_"c, " "c)
' or in Visual Studio 2015 and newer:
Dim Contanct As String = NameOf(Test.Personal_Contanct).Replace("_"c, " "c)
You could just create a new type
''' <completionlist cref="Test"/>
Class Test
Private Key As String
Public Shared ReadOnly Contact As Test = New Test("Personal Contanct")
Public Shared ReadOnly PersonalInfo As Test = New Test("Personal Info")
Private Sub New(key as String)
Me.Key = key
End Sub
Public Overrides Function ToString() As String
Return Me.Key
End Function
End Class
and when you use it, it kinda looks like an enum:
Sub Main
DoSomething(Test.Contact)
DoSomething(Test.PersonalInfo)
End Sub
Sub DoSomething(test As Test)
Console.WriteLine(test.ToString())
End Sub
output:
Personal Contanct
Personal Info
How about using Tagging. Something like:
Public Enum MyEnum
<StringValue("Personal Contact")>Contact
<StringValue("My PersonalInfo")>PersonalInfo
End Enum
You would have to write the StringValue attribute as:
Public Class StringValueAttribute
Inherits Attribute
Public Property Value As String
Public Sub New(ByVal val As String)
Value = val
End Sub
End Class
To get it out:
Public Function GetEnumByStringValueAttribute(value As String, enumType As Type) As Object
For Each val As [Enum] In [Enum].GetValues(enumType)
Dim fi As FieldInfo = enumType.GetField(val.ToString())
Dim attributes As StringValueAttribute() = DirectCast(fi.GetCustomAttributes(GetType(StringValueAttribute), False), StringValueAttribute())
Dim attr As StringValueAttribute = attributes(0)
If attr.Value = value Then
Return val
End If
Next
Throw New ArgumentException("The value '" & value & "' is not supported.")
End Function
Public Function GetEnumByStringValueAttribute(Of YourEnumType)(value As String) As YourEnumType
Return CType(GetEnumByStringValueAttribute(value, GetType(YourEnumType)), YourEnumType)
End Function
And then a call to get the Enum (using string attribute):
Dim mEnum as MyEnum = GetEnumByStringValueAttribute(Of MyEnum)("Personal Contact")
To get the "Attribute" value out (removed handling 'Nothing' for clarity):
Public Function GetEnumValue(Of YourEnumType)(p As YourEnumType) As String
Return DirectCast(Attribute.GetCustomAttribute(ForValue(p), GetType(StringValueAttribute)), StringValueAttribute).Value
End Function
Private Function ForValue(Of YourEnumType)(p As YourEnumType) As MemberInfo
Return GetType(YourEnumType).GetField([Enum].GetName(GetType(YourEnumType), p))
End Function
And the call to get the string attribute (using Enum):
Dim strValue as String = GetEnumValue(Of MyEnum)(MyEnum.Contact)
How can i get this value using ENUM? or anyother way to do it.
There are three common ways of mapping enum values to strings:
Use a Dictionary(Of YourEnumType, String)
Decorate the enum values with attributes (e.g. DescriptionAttribute) and fetch them with reflection
Use a Switch statement
The first of these options is probably the simplest, in my view.
I know this is an old post put I found a nice solution that worth sharing:
''' <summary>
''' Gives acces to strings paths that are used often in the application
''' </summary>
Public NotInheritable Class Link
Public Const lrAutoSpeed As String = "scVirtualMaster<.lrAutoSpeed>"
Public Const eSimpleStatus As String = "scMachineControl<.eSimpleStatus>"
Public Const xLivebitHMI As String = "scMachineControl<.xLivebitHMI>"
Public Const xChangeCycleActive As String = "scMachineControl<.xChangeCycleActive>"
End Class
Usage:
'Can be anywhere in you applicaiton:
Link.xChangeCycleActive
This prevents unwanted extra coding, it's easy to maintain and I think this minimizes extra processor overhead.
Also visual studio shows the string attributes right after you type "Link"
just like if it is a regular Enum
If all you want to do is display the enums in a list or combo, you can use tagging such as
Private Enum MyEnum
Select_an_option___
__ACCOUNTS__
Invoices0
Review_Invoice
__MEETINGS__
Scheduled_Meetings0
Open_Meeting
Cancelled_Meetings0
Current_Meetings0
End Enum
Then pull the MyEnum into a string and use Replace (or Regex) to replace the tags: "___" with "...", "__" with "**", "_" with " ", and remove trailing numbers. Then repack it up into an array and dump it into a combobox which will look like:
Select an option...
**ACCOUNTS**
Invoices
Review Invoice
**MEETINGS**
Scheduled Meetings
Open Meeting
Cancelled Meetings
Current Meetings
(You can use the numbers to, say, disable a text field for inputting an invoice number or meeting room. In the example, Review Invoice and Open Meeting might be expecting additional input so a text box might be enabled for those selections.)
When you parse the selected combo item, the enumeration will work as expected but you only really need to add a single line of code - the text replacement - to get the combo to look as you wish.
(The explanation is about 10 times as involved as the actual solution!)
This technique from Microsoft - "How to: Determine the String Associated with an Enumeration Value (Visual Basic)" - will be useful in some situations (it didn't help with mine unfortunately though :( ). Microsoft's example:
VB:
Public Enum flavorEnum
salty
sweet
sour
bitter
End Enum
Private Sub TestMethod()
MsgBox("The strings in the flavorEnum are:")
Dim i As String
For Each i In [Enum].GetNames(GetType(flavorEnum))
MsgBox(i)
Next
End Sub

Visual basic and Json.net Web request

Basically what im trying to do is make a program that list game information for league of legends.. using there API to extract data. how this works is you Search there username and it returns an integer linked to that account, you then use that integer to search for all of the information for that account, EG account level, wins, losses, etc.
I've run into a problem i can't seem to figure out.. Please not that I'm very new to Json.net so have little experience about working with it.. Below is how the search for the user ID is found, The First section is the Username Minus Any spaces in the name the next is the ID which is the information i require.
{"chucknoland":{"id":273746,"name":"Chuck Noland","profileIconId":662,"summonerLevel":30,"revisionDate":1434821021000}}
I must be declaring the variables wrong in order to obtain the data as everything i do it returns as 0.
these are the following class i have to store the ID within
Public Class ID
Public Shared id As Integer
Public Shared name As String
End Class
Looking at a previous example seen here Simple working Example of json.net in VB.net
They where able to resolve there issue by making a container class with everything inside it.. My problem is that The data i seek i always changing.. The first set will always be different to the "Chucknoland" that's displayed in the example.. is someone able to explain how i could go about extracting this information?
Please note that the variables rRegion has the value of what server there on, Chuck Noland is on OCE, and sSearch is the Username.. Due to Problems with API keys i had to remove the API key from the code... But the URL returns the Json Provided.
'URL string used to grab Summoner ID
jUrlData = "https://oce.api.pvp.net/api/lol/" + rRegion + "/v1.4/summoner/by-name/" + sSearch +
' Create a request for URL Data.
Dim jsonRequest As WebRequest = WebRequest.Create(jUrlData)
'request a response from the webpage
Dim jsonResponse As HttpWebResponse = CType(jsonRequest.GetResponse(), HttpWebResponse)
'Get Data from requested URL
Dim jsonStream As Stream = jsonResponse.GetResponseStream()
'Read Steam for easy access
Dim jsonReader As New StreamReader(jsonStream)
'Read Content
Dim jsonResponseURL As String = jsonReader.ReadToEnd()
jUrlString = jsonResponseURL
this is the request i have to obtain the information, and this is the code i tried to use to display the ID for that json.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim obj As ID
obj = JsonConvert.DeserializeObject(Of ID)(jUrlString)
MsgBox(obj.id)
End Sub
Is anyone able to explain how i can go about getting this to work?
One way to handle this would be to get the item into a Dictionary where the keys are the property names.
The class you have is not quite right unless you only want name and id and not the rest of the information. But using a Dictionary you wont need it anyway. The "trick" is to skip over the first part since you do not know the name. I can think of 2 ways to do this, but there are probably more/better ways.
Since json uses string keys pretty heavily, create a Dictionary, then get the data from it for the actual item:
jstr = ... from whereever
' create a dictionary
Dim jResp = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(jstr)
' get the first/only value item
Dim jobj = jResp.Values(0) ' only 1 item
' if you end up needing the name/key:
'Dim key As String = jResp.Keys(0)
' deserialize first item to dictionary
Dim myItem = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(jobj.ToString)
' view results
For Each kvp As KeyValuePair(Of String, Object) In myItem
Console.WriteLine("k: {0} v: {1}", kvp.Key, kvp.Value.ToString)
Next
Output:
k: id v: 273746
k: name v: Chuck Noland
k: profileIconId v: 662
k: summonerLevel v: 30
k: revisionDate v: 1434821021000
Using String, String may also work, but it would convert numerics to string (30 becomes "30") which is usually undesirable.
While poking around I found another way to get at the object data, but I am not sure if it is a good idea or not:
' parse to JObject
Dim js As JObject = JObject.Parse(jstr)
' 1 = first item; 2+ will be individual props
Dim jT As JToken = js.Descendants(1)
' parse the token to String/Object pairs
Dim myItem = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(jT.ToString)
Same results.

Get items in response object via javaScriptSerializer.Deserialize

I have a dropbox webhook hitting my page. I need to grab the list of users in the response which I will process later on a separate thread. I can see the users in the data variable but I don't know how to extract the list of users in the object. Basically I want to populate an array of users which I can loop through and do some other processing. Hope this makes sense.
This is what the object looks like:
{
"delta": {
"users": [
12345678,
23456789,
...
]
}
}
This is the code I tried and like I say, I can see the string in data:
Dim strJSON = [String].Empty
Context.Request.InputStream.Position = 0
Using inputStream = New StreamReader(Context.Request.InputStream)
strJSON = inputStream.ReadToEnd()
End Using
Dim javaScriptSerializer As New JavaScriptSerializer()
Dim data As Object = javaScriptSerializer.Deserialize(strJSON, GetType(Object))
I would like an array of the users. Hope you can help.
Just make some classes for your response data:
Class Data
Public Property delta As Delta
End Class
Class Delta
' If you would rather have a list you can declare this As List(Of Integer) instead
Public Property users As Integer()
End Class
You can then deserialize directly into the classes:
Dim data As Data = javaScriptSerializer.Deserialize(Of Data)(strJSON)
From there you can work with your data easily enough:
For Each user As Integer In data.delta.users
Console.WriteLine(user)
Next

dynamically change querystring in asp.net

Our client is asking to encrypt the URL because it is passing values in the query string. We have used encryption and are able to encrypt the URL; however, existing code uses querystring["var"] in so many places and fails because of the encrypted URL. Hence, on page load, we will have to decrypt the URL. If I decrypt and alter the query string using response.redirect, then again query string will be visible in the URL and can be misused.
Please help.
EDIT
I was reading about RESTfull web service. I have not yet understood entire concept. I wonder if I can use this with my application to hide query string. Please let me know if so.
Thanks.
One way to achieve this with little headache is to decrypt the query string as you currently do, then set its values to some object which can be stored in the session. Storing it in a session variable would be useful if you wanted to exclude this information (hide) from the query string - you'd essentially be passing the data around behind the scenes.
Once stored in session, you would then change your code, such that wherever you use querystring["var"], you will instead refer to the object that has been stored in the session.
Edit
Note, though, that this doesn't have to be relegated to a single value. This object can have multiple properties each representing a query string value:
MyQueryStringObject myQueryStringObject = new MyQueryStringObject(SomeUrl);
//MyQueryStringObject decrypts the query string and assigns the values to properties in its constructor
string abc = myQueryStringObject.abc;
string xyz = myQueryStringObject.xyz;
Now, that uses properties to represent each query string value. You may have tons of them. In that case, you can store the values into some sort of Dictionary or a NameValueCollection perhaps.
There are various ways to achieve this which I think is beyond topic, but, note that the key to all of this, the very essence is to simply decrypt the url on the server (during postback) and save the unencrypted data into a session variable should you want to hide it from the URL.
There is a much better way of going about this. I deal with a client with that has the same requirement. This class has soared through security scans as well.
Public Class QueryStringManager
Public Shared Function BuildQueryString(ByVal url As String, ByVal queryStringValues As NameValueCollection) As String
Dim builder As New StringBuilder()
builder.Append(url & "?")
Dim count = queryStringValues.Count
If count > 0 Then
For Each key In queryStringValues.AllKeys
Dim value As String = queryStringValues(key)
Dim param As String = BuildParameter(key, value)
builder.Append(param)
Next
End If
Return builder.ToString()
End Function
Public Shared Function DeconstructQueryString(ByVal Request As HttpRequest) As NameValueCollection
Dim queryStringValues As New NameValueCollection
For Each key In Request.QueryString.AllKeys
Dim value As String = Request.QueryString(key)
value = DeconstructParameter(value)
queryStringValues.Add(key, value)
Next
Return queryStringValues
End Function
Private Shared Function BuildParameter(ByVal key As String, ByVal value As String) As String
Dim builder As New StringBuilder()
builder.Append(key.ToString() & "=")
value = GetSafeHtmlFragment(value)
Dim encrypt As Security = New Security()
value = encrypt.Encrypt(value)
builder.Append(value)
builder.Append("&")
Return builder.ToString()
End Function
Public Shared Function DeconstructParameter(ByVal value As Object) As String
Dim decrypt As New Security()
value = decrypt.Decrypt(value)
value = GetSafeHtmlFragment(value)
End Function
End Class
Use
Dim nvc As NameValueCollection = New NameValueCollection()
nvc.Add("value", 1)
Dim builtUrl As String = QueryStringManager.BuildQueryString(url, nvc)
Response.Redirect(builtUrl, false);
Then when you get to the page you simply write:
Dim decryptedValues As NameValueCollection = QueryStringManager.DeconstructQueryString(Request)
The reason why I use NameValueCollection is because that's the same type as QueryString. You can build on to the class to add an object into the QueryString based on it's properties and their values as well. This keeps all of the complex and tedious logic encapsulated away.

Using arrays with asp.net and VB

Sorry, I'm sure this is something that has been covered many times, but I can't find quite what I am after.
I have a single row data table which contains various settings which are used within my web system. I have been toying with turning this into an XML document instead of the single row datatable, would that make more sense?
Anyway, so, given that this is one record, there is a field called "locations," this field contains data as follows:
locationName1,IpAddress|locationName2,IpAddress|etc
The ipAddress is just the first 5 digits of the IP and allows me to ensure that logins to certain elements (admin section managed by staff) can only be accepted when connected from a company computer (ie using our ISP) - this is a largely unnecessary feature, but stops kids I employ logging in at home and stuff!
So, as the user logs in, I can check if the IP is valid by a simple SQL query.
SELECT ips FROM settings WHERE loginLocations LIKE '%" & Left(ipAddress, 5) & " %'
What I need to be able to do now, is get the name of the users location from the dataField array.
I've come up with a few long winded looping procedures, but is there a simple way to analyse
locationName1,IpAddress1|locationName2,IpAddress2|etc
as a string and simply get the locationName where LoginIp = IpAddressX
... or am I going about this in a totally ridiculous way and should turn it into an xml file? (which will then create a whole load of other questions for you about parsing XML!!)
u can split the string in Vb.net and the send it to a query or anything
'Split the string on the "," character
Dim parts As String() = s.Split(New Char() {","c})
In SQL Server, these are the functions of interest in extracting a sub-string:
CHARINDEX
SUBSTRING
LENGTH
You can google the details about them (e.g. CHARINDEX at http://msdn.microsoft.com/en-us/library/ms186323.aspx). With these, you'll need to use computed columns in your query to extract that location name.
If it's not too late, you may want to devise a new way to layout these elements. For instance, instead of:
locationName1,IpAddress1|locationName2,IpAddress2|etc
How about
{IpAddress1,locationName1}{IpAddress2,locationName2}etc
That way you can use CHARINDEX to locate "{" & Left(ipAddress, 5); from that position, locate ","; then from that position locate the closing "}". From there it should be straightforward to use SUBSTRING to get at the locationName. Be forewarned that this will likely be a messy query (probably built from a few sub-queries, one for each position).
In the end, SpectralGhost's idea to just read in the column and do the extraction in VB is probably the way with the least hassle.
I've decided to do it this way, but would appreciate comments on efficiency.
I've split ipAddress and locationName into two database columns, within the one row, and getting the required data by comparing strings as arrays, as per the code below.
For this particular application I'm only dealing with one record, so it's pretty simple. However, further down the line, I need to product a system for monitoring product sales. from an invoices table.
Each invoice record is a row in the database with items in the invoice held similarly, [item1],[item2] etc. There is another column for quantities [qty1],[qty2] etc, prices [price1],[price2], etc. I'll need to be able to search the database for invoices in which an item number occurs (easy SQL WHERE itemList LIKE %[invNO]%) and then compare arrays to get the quantities and individual prices of each item on that invoice. Extracting these rows as arrays and locating the relevant position in these as per the code below, will work fine, but when the whole operation is looping through several hundred or thousand rows, will this become really slow?
ipList, locationList = list as comma separated string from database record field
Dim ipArray As Array = Split(ipList, ",")
Dim locationArray As Array = Split(locationList, ",")
For i = 0 To UBound(ipArray)
If Left(ipArray(i), 5) = Left(ipAddress, 5) Then
arrayPosition = i
itemFound = "True"
Exit For
End If
Next
location = locationArray(arrayPosition)
'loop through ips then get the position and make the location equal to that
If itemFound <> "True" Then
inValidIP = "True"
End If
I strongly advise that you break those our into database columns and each location is a separate row; had it been done that way in the first place, you wouldn't have the problem you have now.
But since you have it in a single row/column, why not bring that back and simply get the value from .NET?
Dim Source As String = "TestLocationA,127.0|TestLocationB,128.0|TestLocationC,129.0"
Dim Test As String = Source
Dim ToFind As String = "127.0"
Test = Test.Substring(0, Test.IndexOf(ToFind & "|") - 1)
Test = Test.Substring(Test.LastIndexOf("|") + 1)
MsgBox(Test)
OR
Public Class Form1
Private IpLocationList As New List(Of IpLocation)
Private IpToFind As String = ""
Private Class IpLocation
Public Name As String
Public IP As String
Public Sub New(ByVal FullLocation As String)
Me.Name = FullLocation.Substring(0, FullLocation.IndexOf(","))
Me.IP = FullLocation.Substring(FullLocation.IndexOf(",") + 1)
End Sub
End Class
Private Function FindIP(ByVal IpLocationItem As IpLocation) As Boolean
If IpLocationItem.IP = IpToFind Then
Return True
Else
Return False
End If
End Function
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim Source As String = "TestLocationA,127.0|TestLocationB,128.0|TestLocationC,129.0"
Dim LocationList As New List(Of String)
LocationList.AddRange(Split(Source, "|"))
For Each LocationItem As String In LocationList
IpLocationList.Add(New IpLocation(LocationItem))
Next
IpToFind = "127.0"
Dim result As IpLocation = IpLocationList.Find(AddressOf FindIP)
If result IsNot Nothing Then
MsgBox(result.Name)
End If
End Sub
End Class
enter code here
This has the benefit of loading the array one time and not needing to manually loop through arrays.

Resources