searching a list object - vb.net

I have a list:
Dim list As New List(Of String)
with the following items:
290-7-11
1255-7-12
222-7-11
290-7-13
What's an easy and fast way to search if duplicate of "first block" plus "-" plus "second block" is already in the list. Example the item 290-7 appears twice, 290-7-11 and 290-7-13.
I am using .net 2.0

If you only want to know if there are duplicates but don't care what they are...
The easiest way (assuming exactly two dashes).
Boolean hasDuplicatePrefixes = list
.GroupBy(i => i.Substring(0, i.LastIndexOf('-')))
.Any(g => g.Count() > 1)
The fastest way (at least for large sets of strings).
HashSet<String> hashSet = new HashSet<String>();
Boolean hasDuplicatePrefixes = false;
foreach (String item in list)
{
String prefix = item.Substring(0, item.LastIndexOf('-'));
if (hashSet.Contains(prefix))
{
hasDuplicatePrefixes = true;
break;
}
else
{
hashSet.Add(prefix);
}
}
If there are cases with more than two dashes, use the following. This will still fail with a single dash.
String prefix = item.Substring(0, item.IndexOf('-', item.IndexOf('-') + 1));
In .NET 2.0 use Dictionary<TKey, TValue> instead of HashSet<T>.
Dictionary<String, Boolean> dictionary= new Dictionary<String, Boolean>();
Boolean hasDuplicatePrefixes = false;
foreach (String item in list)
{
String prefix = item.Substring(0, item.LastIndexOf('-'));
if (dictionary.ContainsKey(prefix))
{
hasDuplicatePrefixes = true;
break;
}
else
{
dictionary.Add(prefix, true);
}
}
If you don't care about readability and speed, use an array instead of a list, and you are a real fan of regular expressions, you can do the following, too.
Boolean hasDuplicatePrefixes = Regex.IsMatch(
String.Join("#", list), #".*(?:^|#)([0-9]+-[0-9]+-).*#\1");

Do you want to stop user from adding it?
If so, a HashTable with the key as first block-second block could be of use.
If not, LINQ is the way to go.
But, it will have to traverse the list to check.
How big can this list be?
EDIT: I don't know if HashTable has generic version.
You could also use SortedDictionary which can take generic arguments.

If you're list contains only strings, then you can simply make a method that takes the string you want to find along with the list:
Boolean isStringDuplicated(String find, List<String> list)
{
if (list == null)
throw new System.ArgumentNullException("Given list is null.");
int count = 0;
foreach (String s in list)
{
if (s.Contains(find))
count += 1;
if (count == 2)
return true;
}
return false;
}
If you're numbers have a special significance in your program, don't be afraid to use a class to represent them instead of sticking with strings. Then you would have a place to write all the custom functionality you want for said numbers.

Related

How to avoid splitting of word with case

Below is the text that I want to split:
string content = "Tonight the warning from the Police commissioner as they crack down on anyone who leaves there house without a 'reasonable excuse'
(TAKE SOT)"
string[] contentList = content.split(' ');
I do not want to split the word i.e (TAKE SOT), if there is a text within parentheses and in an upper case then how to avoid splitting of the part.
Thanks
The split method can have two parameters.The first one delimits the substrings in this instance.The second one is the maximum number of elements expected in the array.
The following code snippet work for me, you can refer to it.
string content = "Tonight the warning from the Police commissioner as they crack down on anyone who leaves there house without a 'reasonable excuse' (TAKE SOT)";
string[] contents = content.Split(" ", content.Substring(0, content.IndexOf("(")).Split(" ").Length);
And this is the result of the code:
I use the method Split(String, Int32, StringSplitOptions)
Later after doing some research I found a solution for the problem:
public class Program
{
public static void Main()
{
string BEFORE_AND_AFTER_SOUND_EFFECT = #"\(([A-Z\s]*)\)";
List<string> wordList = new List<string>();
string content = "Tonight the warning from the Police commissioner as they (VO) crack down on anyone who leaves there house without a 'reasonable excuse' (TAKE SOT) INCUE:police will continue to be out there.";
GetWords(content, wordList, BEFORE_AND_AFTER_SOUND_EFFECT);
foreach(var item in wordList)
{
Console.WriteLine(item);
}
}
private static void GetWords(string content, List<string> wordList, string BEFORE_AND_AFTER_SOUND_EFFECT)
{
if(content.Length>0)
{
if (Regex.IsMatch(content, BEFORE_AND_AFTER_SOUND_EFFECT))
{
int textLength = content.Substring(0, Regex.Match(content, BEFORE_AND_AFTER_SOUND_EFFECT).Index).Length;
int matchLength = Regex.Match(content, BEFORE_AND_AFTER_SOUND_EFFECT).Length;
string[] words = content.Substring(0, Regex.Match(content, BEFORE_AND_AFTER_SOUND_EFFECT).Index - 1).Split(' ');
foreach (var word in words)
{
wordList.Add(word);
}
wordList.Add(content.Substring(Regex.Match(content, BEFORE_AND_AFTER_SOUND_EFFECT).Index, Regex.Match(content, BEFORE_AND_AFTER_SOUND_EFFECT).Length));
content = content.Substring((textLength + matchLength) + 1); // Remaining content
GetWords(content, wordList, BEFORE_AND_AFTER_SOUND_EFFECT);
}
else
{
wordList.Add(content);
content = content.Substring(content.Length); // Remaining content
GetWords(content, wordList, BEFORE_AND_AFTER_SOUND_EFFECT);
}
}
}
}
Thanks.

How Do I Return the Index of type T in a Collection based on some criteria?

Kotlin has some pretty cool functions for collections. However, I have come across a problem in which the solution is not apparent to me.
I have a List of Objects. Those Objects have an ID field which coincides with a SQLite database. SQL operations are performed on the database, and a new list is generated. How can the index of an item from the new list be found based on the "ID" field (or any other field for that matter)?
the Collection.find{} function return the object, but not the index.
indexOfFirst can find the index of the first element of a collection that satisfies a specified predicate.
We have a DB SQlite that a call is made to to retrieve parentList We can obtain the items in the ArrayList with this type of code
fun onDoIt(view: View){
initDB()
for (t in 0..X-1) {
var N:String = parentList[t].dept
// NOTE two syntax here [t] and get(t)
if(t == 1){
var B:String = parentList[0].idD.toString()
println("$$$$$$$$$$$$$$$$$$$$$ ====== "+B)
}
var I:String = parentList.get(t).idD.toString()
println("################### id "+I+" for "+N)
}
}
private fun initDB() {
parentList = db.querySPDept()
if (parentList.isEmpty()) {
title = "No Records in DB"
} else {
X = parentList.size
println("**************************************** SIZE " + X)
title = "SP View Activity"
}
}

How to use Lambda expressions in java for nested if-else and for loop together

I have following Code where i will receive list of names as parameter.In the loop, first i'm assigning index 0 value from list to local variable name. There after comparing next values from list with name. If we receive any non-equal value from list, i'm assigning value of result as 1 and failing the test case.
Below is the Array list
List<String> names= new ArrayList<String>();
names.add("John");
names.add("Mark");
Below is my selenium test method
public void test(List<String> names)
String name=null;
int a=0;
for(String value:names){
if(name==null){
System.out.println("Value is null");
name=value;
}
else if(name.equals(value)){
System.out.println("Received Same name");
name=value;
}
else{
a=1;
Assert.fail("Received different name in between");
}
}
How can i convert above code into lambda expressions?. I'm using cucumber data model, hence i receive data as list from feature file. Since i can't give clear explanation, just posted the example logic i need to convert to lambda expression.
Here's the solution: it cycles all element in your list checking if are all the same.
You can try adding or editing the list so you can have different outputs. I've written the logic, you can easly put it into a JUnit test
List<String> names= new ArrayList<>();
names.add("John");
names.add("Mark");
String firstEntry = names.get(0);
boolean allMatch = names.stream().allMatch(name -> firstEntry.equals(name));
System.out.println("All names are the same: "+allMatch);
Are you looking for duplicates, whenever you have distinct value , set a=1 and say assert to fail. You can achieve this by :
List<String> names= new ArrayList<String>();
names.add("John");
names.add("Mark");
if (names.stream().distinct().limit(2).count() > 1) {
a= 1,
Assert.fail("Received different name in between");
} else {
System.out.println("Received Same name");
}

String is to Substring, as ArrayList is to?

In Java, and many other languages, one can grab a subsection of a string by saying something like String.substring(begin, end). My question is, Does there exist a built-in capability to do the same with Lists in Java that returns a sublist from the original?
This method is called subList and exists for both array and linked lists. Beware that the list it returns is backed by the existing list so updating the original one will update the slice.
The answer can be found in the List API: List#subList(int, int) (can't figure out how to get the link working....)
Be warned, though, that this is a view of the underlying list, so if you change the original list, you'll change the sublist, and the semantics of the sublist is undefined if you structurally modify the original list. So I suppose it isn't strictly what you're looking for...
If you want a structurally independent subsection of the list, I believe you'll have to do something like:
ArrayList<something> copy = new ArrayList<>(oldList.subsection(begin, end));
However, this will retain references to the original objects in the sublist. You'll probably have to manually clone everything if you want a completely new list.
The method is called sublist and can be found here in the javadocs
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#subList(int, int)
You can use subList(start, end)
ArrayList<String> arrl = new ArrayList<String>();
//adding elements to the end
arrl.add("First");
arrl.add("Second");
arrl.add("Third");
arrl.add("Random");
arrl.add("Click");
System.out.println("Actual ArrayList:"+arrl);
List<String> list = arrl.subList(2, 4);
System.out.println("Sub List: "+list);
Ouput :
Actual ArrayList:[First, Second, Third, Random, Click]
Sub List: [Third, Random]
You might just want to make a new method if you want it to be exactly like substring is to String.
public static List<String> sub(List<String> strs, int start, int end) {
List<String> ret = new ArrayList<>(); //Make a new empty ArrayList with String values
for (int i = start; i < end; i++) { //From start inclusive to end exclusive
ret.add(strs.get(i)); //Append the value of strs at the current index to the end of ret
}
return ret;
}
public static List<String> sub(List<String> strs, int start) {
List<String> ret = new ArrayList<>(); //Make a new empty ArrayList with String values
for (int i = start; i < strs.size(); i++) { //From start inclusive to the end of strs
ret.add(strs.get(i)); //Append the value of strs at the current index to the end of ret
}
return ret;
}
If myStrings is an ArrayList of the following Strings: {"do","you","really","think","I","am","addicted","to","coding"}, then sub(myStrings,1,6) would return {"you", "really", "think", "I", "am"} and sub(myStrings,4) would return {"I", "am", "addicted", "to", "coding"}. Also by doing sub(myStrings, 0) it would rewrite myStrings as a new ArrayList which could help with referencing problems.

Get a value from array based on the value of others arrays (VB.Net)

Supposed that I have two arrays:
Dim RoomName() As String = {(RoomA), (RoomB), (RoomC), (RoomD), (RoomE)}
Dim RoomType() As Integer = {1, 2, 2, 2, 1}
I want to get a value from the "RoomName" array based on a criteria of "RoomType" array. For example, I want to get a "RoomName" with "RoomType = 2", so the algorithm should randomize the index of the array that the "RoomType" is "2", and get a single value range from index "1-3" only.
Is there any possible ways to solve the problem using array, or is there any better ways to do this? Thank you very much for your time :)
Note: Code examples below using C# but hopefully you can read the intent for vb.net
Well, a simpler way would be to have a structure/class that contained both name and type properties e.g.:
public class Room
{
public string Name { get; set; }
public int Type { get; set; }
public Room(string name, int type)
{
Name = name;
Type = type;
}
}
Then given a set of rooms you can find those of a given type using a simple linq expression:
var match = rooms.Where(r => r.Type == 2).Select(r => r.Name).ToList();
Then you can find a random entry from within the set of matching room names (see below)
However assuming you want to stick with the parallel arrays, one way is to find the matching index values from the type array, then find the matching names and then find one of the matching values using a random function.
var matchingTypeIndexes = new List<int>();
int matchingTypeIndex = -1;
do
{
matchingTypeIndex = Array.IndexOf(roomType, 2, matchingTypeIndex + 1);
if (matchingTypeIndex > -1)
{
matchingTypeIndexes.Add(matchingTypeIndex);
}
} while (matchingTypeIndex > -1);
List<string> matchingRoomNames = matchingTypeIndexes.Select(typeIndex => roomName[typeIndex]).ToList();
Then to find a random entry of those that match (from one of the lists generated above):
var posn = new Random().Next(matchingRoomNames.Count);
Console.WriteLine(matchingRoomNames[posn]);