Why the checking condition in the inner loop never true? - c#

for (int i = 0; i < ExtractLinks.FilteredLinks.Count; i++)
{
for (int x = 0; x < lockedLinks.Count; x++)
{
if (ExtractLinks.FilteredLinks[i].Contains(lockedLinks[x]))
{
string h = "found";
}
}
}
I want to check if the same link exist in both Lists.
FilteredLinks and lockedLinks both type List
I used a break point and in the FilteredLink i saw this link for example:
http://rotter.net/forum/scoops1/112341.shtml
And in lockedLinks this link:
http://rotter.net/cgi-bin/forum/dcboard.cgi?az=read_count&om=112341&forum=scoops1
Both links lead to the same page. So that's mean both are the same.
So in this case it should stop in the break point i added on : string h = "found";
But since it's never stop there i guess something is wrong with my IF condition.
In case it was found i want to remove the link from the FilteredLinks and also from the lockedLinks to remove what suppose to be the same links from both lists. The links are not identical in the address but they are leading to same page so i consider them as the same/identical and they both should be removed.

If you know the uri format then you can extract the id from the different uri types and compare those:
private static string GetArticleIdFiltered(string filtered)
{
var uri = new Uri(filtered);
return Path.GetFileNameWithoutExtension(uri.LocalPath);
}
private static string GetArticleIdLocked(string locked)
{
var uri = new Uri(locked);
var queryParams = HttpUtility.ParseQueryString(uri.Query);
return queryParams["om"];
}
for (int x = 0; x < lockedLinks.Count; x++)
{
var lockedArticle = GetArticleIdLocked(lockedLinks[x]);
var filteredId = GetArticleIdFiltered(ExtractLinks.FilteredLinks[i]);
if (lockedArticle == filteredId)
{
string h = "found";
}
}
If you know the id is always numeric you can parse it more accurately and compare ints instead of strings.

Related

split a number into an array of strings

There is a list of candidates.
candid: {12,14,16,19,25,64,78}
Code :
for (int i = 0; i < candid.Count; i++)
{
var searchTerm = candid[i].ToString();
var searchItems = searchTerm.ToCharArray().ToString();
foreach (Tran b in transactions)
{
string[] temp = new string[b.itemsUtilities.Count];
int j = 0;
foreach (ItemUtility c in b.itemsUtilities)
{
temp[j] = c.item.ToString();
j = j + 1;
}
if (searchItems.All(a => temp.Contains(a)))
arraye[i] = arraye[i] + (b.transactionUtility);
}
}
I receive the following error:
'string[]' does not contain a definition for 'Contains' and the best
extension method overload 'Queryable.Contains(IQueryable,
char)' requires a receiver of type 'IQueryable'
If code changed from : var searchItems = searchTerm.ToCharArray().ToString();
To : var searchItems = searchTerm.split();
This error is fixed, But this split command does not separate numbers.
I guess you want to separate the numbers into a string[].
var searchItems = searchTerm.ToCharArray().ToString();
This will always create a single string "System.Char[]" so is not what you want.
I guess you want:
string[] searchItems = searchTerm.Select(c => c.ToString()).ToArray();
This should fix the compiler error because searchItems.All will now project strings and not chars.
More that a simple missing include, I do think that you are over thinking
your code seems to be simplify as :
for (int i = 0; i < candid.Count; i++)
{
var searchTerm = candid[i].ToString();
foreach (Tran b in transactions)
{
var tmp = b.itemsUtilities.Select(x=> x.item.ToString()).ToList();
if( searchTerm.All(a=> tmp.Contains (a)){
arraye[i] = arraye[i] + (b.transactionUtility);
}
}
}
And you can simplify again instead of for each you filter Trasanction based on the if condition.
And if your candid is 11 no need to check twice for 1 so a simple Distinct() will help here.

removing similar string from an array in c#

Suppose i have array of strings as follows:
string[] array = new string[6];
array[0] = "http://www.s8wministries.org/general.php?id=35";
array[1] = "http://www.s8wministries.org/general.php?id=52";
array[2] = "http://www.ecogybiofuels.com/general.php?id=6";
array[3] = "http://www.stjohnsheriff.com/general.php?id=186";
array[4] = "http://www.stjohnsheriff.com/general.php?id=7";
array[5] = "http://www.bickellawfirm.com/general.php?id=1048";
Now I want to store only one similar occurrence of the string ie http://www.s8wministries.org/general.php?id=35 discarding any other string that has http://www.s8wministries.org and store it in another array.
Please how do I go about this?
my attempt is as follows:-
//remove similar string from array storing only one similar in another array
foreach (var olu in array)
{
string findThisString = olu.ToString();
string firstTen = findThisString.Substring(0, 15);
// See if substring is in the table.
int index1 = Array.IndexOf(array, firstTen); //substring is not in table
}
try this with List of string, so you have list of string containing URL, you can use URI class to compare domains:
for(int i = 0; i < strList.Length; i++)
{
Uri uriToCompare = new Uri(strArray[i]);
for(int j = i+1; j < strArray.Length; j++){
Uri uri = new Uri(strArray[j]);
if( uriToCompare.Host == uri.Host){
strList.RemoveAt(j);
}
}
}
Here is how I would approach this
Initialize a hashtable or a dictionary for holding domain names
Loop through each item
Do a string split operation with using '', '.', '/' etc as delimiters - find out the domain by parsing the parts.
Check if the domain name exists in the hashtable. If it does, discard the current entry. If it doesn't exist, insert into the hashtable and also add the current entry to a new list of your selected entries.
Another option would be to sort the entries alphabetically. Go through them one at a time. Select an entry with the domain name. Skip all the next entries with the same domain name. Select the next entry when the domain name changes again.
Let's say the result is to be stored in an array called unique_array and that your current array is called array. Pseudo-code follows:
bool found = false;
for(int i = 0; i < array_size; i++)
{ if(array[i] starts with "http://www.s8wministries.org")
{ if(found) continue;
found = true;
}
add array[i] to end of unique_array;
}
I would go the way of slightly more automation by creating a class that inherits IEqualityComparer (utilizing the great answer to this question):
public class PropertyComparer<T> : IEqualityComparer<T>
{
Func<T, T, bool> comparer;
public PropertyComparer<T>(Func<T, T, bool> comparer)
{
this.comparer = comparer;
}
public bool Equals(T a, T b)
{
return comparer(a, b);
}
public int GetHashCode(T a)
{
return a.GetHashCode();
}
}
Once you have that class - you can use Distinct like this:
var distinctArray = array.Select(s => new Uri(s)).Distinct(new PropertyComparer<Uri>((a, b) => a.Host == b.Host));
That leaves you with an array only containing distinct domains. It's an IEnumerable so you may want to .ToList() it or something, or revert it back to strings from Uris . But I think this method makes for much more readable code.
Please try below Code:
string[] array = new string[6];
array[0] = "http://www.s8wministries.org/general.php?id=35";
array[1] = "http://www.s8wministries.org/general.php?id=52";
array[2] = "http://www.ecogybiofuels.com/general.php?id=6";
array[3] = "http://www.stjohnsheriff.com/general.php?id=186";
array[4] = "http://www.stjohnsheriff.com/general.php?id=7";
array[5] = "http://www.bickellawfirm.com/general.php?id=1048";
var regex = #"http://www.[\w]+.[\w]+";
var distList = new List<string>();
var finalList = new List<string>();
foreach (string str in array)
{
Match match = Regex.Match(str, regex, RegexOptions.IgnoreCase);
if (match.Success)
{
var uniqueUrl = match.Groups[0].Value;
if (!distList.Contains(uniqueUrl))
{
distList.Add(uniqueUrl);
finalList.Add(str);
}
}
}
Here finalList contains the required list of URLs

Foreach loop to check the empty string and assign it a value c#

I dont much idea about Foreach Loop
I have 4 String Variables and i am storing the encrypted values from app.config in those varialbles.My Work is to Detect if there is data in those 4 variables.Even if one doesnt have values i want to pass a default encrypted values to it.I started doing like this......
string EncValue = oEncrypt.EncryptBase64String("NO Data Found");
UpdateOrCreateAppSetting("UserName", ref MPScmUserName);
UpdateOrCreateAppSetting("Password", ref MPScmPassword);
UpdateOrCreateAppSetting("DBUserName", ref MPDbUserName);
UpdateOrCreateAppSetting("DBPassword", ref MPDbPassword);
var list5 = from docs in doc1.Descendants("appender").Elements()
where docs.Name == "file"
select docs;
var element5 = list5.FirstOrDefault();
MPLoadAppConfig = appConfigFile1;
MPErrorLog = element5.Attribute("value").Value;
string[] namesArray = new string[] {
MPScmUserName,MPScmPassword,MPDbUserName,MPDbPassword};
foreach (string i in namesArray)
{
if (i is string)
{
if (i == "")
{
i = EncValue.ToString();
}
}
}
How should i assign default encrypted value to the strings in that array which is a empty string. Please Help me....
You don't need to say if (i is string) because it's already a string.
In another if block you may say
if(string.IsNullOrEmpty(i))
{
}
or you may use:
string[] arr = new string[] { "","A"};
for (int i = 0; i < arr.Length; i++)
{
if (string.IsNullOrEmpty(arr[i]))
{
arr[i] = "Hello";
}
}
Looping on the string array and changing the value of current string doesn't means you are changing the value of the string inside the array. When foreach loops on your array it returns a new string instance in i, so changing that i don't change the value in namesArray.
You need a traditional for loop with an indexer to access directly to the namesArray
for(int i = 0; i < namesArray.Length; i++)
{
if (namesArray[i] == string.Empty)
{
namesArray[i] = EncValue.ToString();
}
}
No need for the if (i is string) part because you already know it's a string. You should probably also use string.IsNullOrWhiteSpace(); to test for an empty string.
Edit (shameless copy from Mark's answer):
for (int i = 0; i < namesArray.Length; ++i)
{
if (string.IsNullOrWhiteSpace(namesArray[i]))
{
namesArray[i] = EncValue.ToString();
}
}
You can't modify the variable in a foreach loop. Your code should give you the following compile error:
Cannot assign to 'i' because it is a 'foreach iteration variable'
You could do this using LINQ:
namesArray = namesArray.Select(s => s == "" ? EncValue.ToString() : s).ToArray();
Alternatively you could use a simple for loop:
for (int i = 0; i < namesArray.Length; ++i)
{
if (namesArray[i] == "")
{
namesArray[i] = EncValue.ToString();
}
}
string[] newNamesArray =
Enumerable.Select(namesArray, s => s == "" ? EncValue : s).ToArray();

Loop inside a array within a dictionary

Hi I have a quick question, which is the easiest way to loop inside an array that is within an object in a dictionary using C#?
The dictionary contain groups and groups have an array called tags, I have search for a tag and return a list of groups that contain that tag
I created a solution but it returns too many doubles when I apply it.
List<Programme> toReturn = new List<Programme>();
// might need to ask getprogramme service to do the iteriation and retun a value
foreach (Programme programme in programmes.Values)
{
if (message.Programme.Tags[0] != null)
{
int i;
int u;
foreach (KeyValuePair<string, Programme> entry in programmes)
{
// for (i = 0; i < message.Group.Tags.Length; i++)
for (i = 0; i < entry.Value.Tags.Length; i++)
//foreach (string i in message.Group.Tags)
{
for (u = 0; u < message.Programme.Tags.Length; u++)
{
// Compare the Name of the entry to the Name in the message (string comparison)
if (entry.Value.Tags[i].Equals(message.Programme.Tags[u]))
{
// If we found the group, set the return value and then break from the loop
toReturn.Add(programme);
break;
}
}
}
}
}
The easiest way is to use LINQ:
var res = groups.Where(g => g.Value.Any(t => t.Equals("search_tag")));

When searching for an item in a generic list should I use LINQ or Contains?

I have a generic List and I have to find a particular string in this list. Could you please let me know which is the best approach in the below?
if (strlist.Contains("Test"))
{
// String found
}
or
string res = (from d in strlist where d == "Test" select d).SingleOrDefault();
if (res == "Test")
{
//found
}
Please consider the list may be very big populated from database. Your thoughts on this are highly appreciated.
If you have List<string> (or even IEnumerable<string>) and Contains meets your needs, then use Contains.
If you need some extra handling that Contains doesn't provide, I would suggest using Any():
if(strList.Any(s => s.StartsWith("Tes"))
{
// Found
}
The two methods will behave differently if there is more than one match; the first one will return true and the second one will throw an exception.
To correct that, change SingleOrDefault to FirstOrDefault.
To answer the question, you should call Contains if you're searching for an exact match and Any if you aren't.
For example:
if (strings.Contains("SomeString", StringComparer.OrdinalIgnoreCase))
if (strings.Any(s => s.StartsWith("b"))
You really should use HashSet<string> as the the performance of Contains is dramatically better. Now if you need to use a list for other operations you can simply have both available.
var list = BuildListOfStrings();
var set = new HashSet<string>(list);
if (set.Contains("Test"))
{
// ...
}
Now you have the ability to find items in the set as a O(1) operation.
Test
static void Main(string[] args)
{
var lst = GenerateStrings().Take(5000000).ToList();
var hsh = new HashSet<string>(lst);
var found = false;
var count = 100;
var sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
hsh = new HashSet<string>(lst);
}
Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks / count));
sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
found = lst.Contains("12345678");
}
Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks / count));
sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
found = hsh.Contains("12345678");
}
Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks / count));
Console.WriteLine(found);
Console.ReadLine();
}
private static IEnumerable<string> GenerateStrings()
{
var rnd = new Random();
while (true)
{
yield return rnd.Next().ToString();
}
}
Result
0.308438 s
0.0197868 s
0.0 s
So what does this tell us? If you are making a small amount of calls to Contains use a List<string>, otherwise use a HashSet<string>.

Categories