Loop inside a array within a dictionary - c#

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")));

Related

Adding to List<string> but having trouble with the items getting added

I have 2 lists with 200 items in each.
List A contains the names of the products.
List B contains the prices of the products.
I have another list (List C) with 250 items inside which include names and prices of products.
Now, I am trying to compare the names of List A to see if they exist in List C and if they do I want to use the price in List C.
This is what I've tried so far:
foreach (var item in wiznzList)
{
for (int j = 0; j < nameList.Count; j++)
{
if (nameList[j] == item.ProductName)
{
wizNzPriceList.Add(item.Price);
}
else
{
wizNzPriceList.Add("No Product");
}
}
}
I want to go through the list of names and check if they exist in List C if they do I want to add the price from List C and if it doesn't exist I want it to write No Product.
So, in the end I want 3 lists with 200 items in each.
Instead, when I run this I get 10040000 items added into the list. Could someone please point me in the right direction.
If i understand your problem correctly (and the jury is out on that)
You could use ToDictionary and Select
var dict = products.ToDictionary(x => x.ProductName, x => x.Price);
var results = names.Select(x => dict.TryGetValue(x, out var value) ? value.ToString() : "No Product");
Note : You could use Any for O(n^2) time complexity. However, ToDictionary would be more efficient
I have found a code that does what you want it to do !
Object Product(string pName, float pPrice).
listA list of Products so you can store and change price.
listB list of float, not used.
list C list of Products with pName and pPrice.
The CompareA_With_C() method first checks for same products and if true put price of list C in listA and breaks out of inner loop.
The else if statement waits till the loop has gone through the whole of listC and if no pName match found, changes pName to "No Product" in listA.
Code :
void CompareA_With_C()
{
for (int i = 0; i < listA.Count; i++)
{
for (int j = 0; j < listC.Count; j++)
{
string a = listA[i].pName;
string c = listC[j].pName;
if (string.Equals(a, c))
{
listA[i].pPrice = listC[j].pPrice;
break;
}
else if (j == (listC.Count - 1))
{
listA[i].pName = "No Product";
listB[i] = 0.0f;
}
}
}
}
You can try to use LINQ and replace your inner loop with Any method.
foreach (var item in wiznzList)
{
if (nameList.Any(p => p == item.ProductName)
{
wizNzPriceList.Add(item.Price);
}
else
{
wizNzPriceList.Add("No Product");
}
}
I was able to solve my problem by using the code below, Thank you very much Crispi.
for (int i = 0; i < nameList.Count; i++)
{
for (int j = 0; j < wiznzList.Count; j++)
{
string a = nameList[i];
string c = wiznzList[j].ProductName;
if (string.Equals(a, c))
{
wizNzPriceList.Add(wiznzList[j].Price);
break;
}
else if (j == (wiznzList.Count - 1))
{
wizNzPriceList.Add("No Product");
}
}
}
I now get 200 results as required. Thank you everyone for your time.

Why the checking condition in the inner loop never true?

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.

Using sortedList to count words in a List

For my homework, I have to use a SortedList to count words in a List with SortedList taking each entry and sorting it in alphabetical order before inserting. When it comes to display the data to the user, the data displayed should be displayed with sorting according to value instead of key.
Below is my attempt at this but I am getting 3 errors and I don't know how to resolve it. I am not allowed to use LINQ for this.
List<string> words = new List<string>(); <--- Already populated
This is my code of this implementation and I get 3 errors:
SortedList<string, int> d = new SortedList<string, int>();
bool InsideOfList = false;
foreach (string word in words)
{
InsideOfList = false;
foreach (KeyValuePair<string, int> keyvalPair in d)
{
if (keyvalPair.Key == word)
{
keyvalPair.Value += 1;
InsideOfList = true;
}
}
if (InsideOfList == false)
{
d.Add(word,1);
}
}
//Now instead of sorting by key I want to sort by value instead
SortedList<int, string> tempSortList = new SortedList<int, string>();
foreach (KeyValuePair<string, int> keyvalPair in d)
{
//trying to swap the value of previous SortedList with the Key of the new SortedList
tempSortList.Add(keyvalPair.Value, keyvalPair.Key);
}
for (int i = 0; i < 20; i++)
{
Console.WriteLine("\t{0}:\t{1}", tempSortList.GetKey(i), tempSortList.GetByIndex(i));
}
Here are my errors:
Property or indexer 'System.Collections.Generic.KeyValuePair<string,int>.Value' cannot be assigned to -- it is read only
'System.Collections.Generic.SortedList<int,string>' does not contain a definition for 'GetKey'
'System.Collections.Generic.SortedList<int,string>' does not contain a definition for 'GetByIndex'
You are confusing two things here. One is SortedList() and other is SortedList().
GetKey and GetKeyList are not present in SortedList(). You can use this instead of GetKey
tempSortList.ElementAt(index); // This will return you a KeyValuePair.
And for the first error you cannot assign value keyvalPair.Value has only getter. So you cannot set its value by doing += 1.
This is not quite good. Needs some improvement but it will work.
for (int i = 0; i < d.Count; i++)
{
if (d.ElementAt(i).Key == word)
{
d.Values[i] += 1;
}
}
or
for (int i = 0; i < d.Count; i++)
{
if (d.ElementAt(i).Key == word)
{
var val = d.ElementAt(i).Value + 1;
d.RemoveAt(i);
d.Add(word, val);
}
}
Please modify this line and check if it works. it should.
Console.WriteLine("\t{0}:\t{1}", tempSortList.GetKey(i), tempSortList.GetByIndex(i));
to
var key = tempSortedList.Keys[i];
var value = tempSortedList.Values[i];
Console.WriteLine("\t{0}:\t{1}", key, value);

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();

Looping through x number of arrays

How do I loop through x number of arrays and visit all combinations of all cells in all of the arrays? The problem here is there can be x number of arrays of some items inside. For instance,
List<List<string>> _arrays = GetArrayInformation();
I want to compare all the string inside each array with all the other arrays and the strings inside of each array. Do I use while like
while(i < _arrays.Count)
Thanks for your answer. The answer seems simple but when you think about it is kind of tricky and hard.
Update:
Thanks for your answers. I can do this with a 3 arrays like
for(int i = 0; i < _arrays[0].Count; i++) {
for(int l = 0; l < _arrays[1].Count; l++) {
for(int m = 0; m < _arrays[2].Count; m++) {
string _hello = _arrays[0][i] + "|" + _arrays[1][l] + "|" + _arrays[2][m];
}
}
}
Because I have dynamic number of arrays, it gets tricky.
foreach(var array in _arrays)
{
foreach(var s in array)
{
foreach(var otherArray in _arrays)
{
if(otherArray == array) continue;
if(otherArray.Contains(s)) {} // not sure what you want to do
}
}
}
this will loop through every single string seeing if it is in any other array.... it's the straightforward approach, but not very efficient and will duplicate work.
There is no enough information is here
If you need to find elements that exists in few array You will use something like this:
var multipleWords = _arrays
.SelectMany(items => items.Distinct())
.GroupBy(item => item)
.Select(group => new {Item = group.Key, Count = group.Count()})
.Where(item => item.Count > 1)
.Select(item => item.Item)
.ToArray();
multipleWords will contain each word from the all these arrays that exists in two or more arrays
You could use a recursive search function.
public Search<T>(object o, string comparestring)
{
if(o is List<string>)
{
//Compare to your string
}
else
{
//Call this search function with the type of the object in the list.
//Will iterate through all of your strings recursively.
Type t = o.GetType().GetGenericArguments()[0];
foreach( object osub in (T)o)
Search<t>( ((t)o),comparestring)
}
}

Categories