I am trying to use hash table in linq to fetch the key whose value is ABC.
What I have done so far:
Hashtable h=new Hashtable ();
h.Add(1 , "ABC");
h.Add(2 , "AgC");
h.Add(3 , "ABC");
h.Add(4 , "AhC");
Expected output: 1, 3 (keys having value "ABC")
ICollection c= h.Keys;
var posi= from a in c
where h[a]="ABC"
select a;
But the above query is not working and giving compile time error.
The error is:
could not find an implementation of the query pattern for source type 'System.Collections.ICollection'.
What I am doing wrong? I am new to C#. How to use Hashtable in LINQ?
You should not use non-generic HashTable to start with. Use generic Dictionary<int, string> instead:
var d = new Dictionary<int, string>();
d.Add(1 , "ABC");
d.Add(2 , "AgC");
d.Add(3 , "ABC");
d.Add(4 , "AhC");
var posi = from a in d
where a.Value == "ABC"
select a.Key;
Use a Dictionary<int, string> instead of a Hashtable (see here for why) then do the following:
var dist = new Dictionary<int, string>();
dist.Add(1 , "ABC");
dist.Add(2 , "AgC");
dist.Add(3 , "ABC");
dist.Add(4 , "AhC");
var keys = dist.Where(d=> d.Value == "ABC").Select(d=> d.Key);
But If you want Hastable, Then please take a look this link
link 1
link 2
But My opinion is, Please use Dictionary .
Because Dictionary is a generic collections, And It's are a lot faster as there's no boxing/unboxing.
If you really want to use that HashTable instead of the Dictionary you can do the following:
var posi = from a in c.Cast<int>()
where h[a] == "ABC"
select a;
You just need to do this to get position:
int indexOf ( object s, Hashtable h )
{
foreach ( DictionaryEntry e in h )
if ( e.Value.Equals(s) )
return (int)e.Key;
return -1;
}
and call it like this:
var posi = indexOf("ABC", yourHashTable);
but it is true that using Dictionary would be much easier.
Related
I have below code in c# 4.0.
//Dictionary object with Key as string and Value as List of Component type object
Dictionary<String, List<Component>> dic = new Dictionary<String, List<Component>>();
//Here I am trying to do the loping for List<Component>
foreach (List<Component> lstComp in dic.Values.ToList())
{
// Below I am trying to get first component from the lstComp object.
// Can we achieve same thing using LINQ?
// Which one will give more performance as well as good object handling?
Component depCountry = lstComp[0].ComponentValue("Dep");
}
Try:
var firstElement = lstComp.First();
You can also use FirstOrDefault() just in case lstComp does not contain any items.
http://msdn.microsoft.com/en-gb/library/bb340482(v=vs.100).aspx
Edit:
To get the Component Value:
var firstElement = lstComp.First().ComponentValue("Dep");
This would assume there is an element in lstComp. An alternative and safer way would be...
var firstOrDefault = lstComp.FirstOrDefault();
if (firstOrDefault != null)
{
var firstComponentValue = firstOrDefault.ComponentValue("Dep");
}
[0] or .First() will give you the same performance whatever happens.
But your Dictionary could contains IEnumerable<Component> instead of List<Component>, and then you cant use the [] operator. That is where the difference is huge.
So for your example, it doesn't really matters, but for this code, you have no choice to use First():
var dic = new Dictionary<String, IEnumerable<Component>>();
foreach (var components in dic.Values)
{
// you can't use [0] because components is an IEnumerable<Component>
var firstComponent = components.First(); // be aware that it will throw an exception if components is empty.
var depCountry = firstComponent.ComponentValue("Dep");
}
You also can use this:
var firstOrDefault = lstComp.FirstOrDefault();
if(firstOrDefault != null)
{
//doSmth
}
for the linq expression you can use like this :
List<int> list = new List<int>() {1,2,3 };
var result = (from l in list
select l).FirstOrDefault();
for the lambda expression you can use like this
List list = new List() { 1, 2, 3 };
int x = list.FirstOrDefault();
You can do
Component depCountry = lstComp
.Select(x => x.ComponentValue("Dep"))
.FirstOrDefault();
Alternatively if you are wanting this for the entire dictionary of values, you can even tie it back to the key
var newDictionary = dic.Select(x => new
{
Key = x.Key,
Value = x.Value.Select( y =>
{
depCountry = y.ComponentValue("Dep")
}).FirstOrDefault()
}
.Where(x => x.Value != null)
.ToDictionary(x => x.Key, x => x.Value());
This will give you a new dictionary. You can access the values
var myTest = newDictionary[key1].depCountry
Try this to get all the list at first, then your desired element (say the First in your case):
var desiredElementCompoundValueList = new List<YourType>();
dic.Values.ToList().ForEach( elem =>
{
desiredElementCompoundValue.Add(elem.ComponentValue("Dep"));
});
var x = desiredElementCompoundValueList.FirstOrDefault();
To get directly the first element value without a lot of foreach iteration and variable assignment:
var desiredCompoundValue = dic.Values.ToList().Select( elem => elem.CompoundValue("Dep")).FirstOrDefault();
See the difference between the two approaches: in the first one you get the list through a ForEach, then your element. In the second you can get your value in a straight way.
Same result, different computation ;)
There are a bunch of such methods:
.First .FirstOrDefault .Single .SingleOrDefault
Choose which suits you best.
var firstObjectsOfValues = (from d in dic select d.Value[0].ComponentValue("Dep"));
I would to it like this:
//Dictionary object with Key as string and Value as List of Component type object
Dictionary<String, List<Component>> dic = new Dictionary<String, List<Component>>();
//from each element of the dictionary select first component if any
IEnumerable<Component> components = dic.Where(kvp => kvp.Value.Any()).Select(kvp => (kvp.Value.First() as Component).ComponentValue("Dep"));
but only if it is sure that list contains only objects of Component class or children
I am trying to import values from a .txt file into my dictionary. The .txt file is formatted like this:
Donald Duck, 2010-04-03
And so on... there is 1 entry like that on each line. My problem comes when I try to add the split strings into the dictionary.
I am trying it like this: scoreList.Add(values[0], values[1]); But it says that names doesn't exist in the context. I hope someone can point me in the correct direction about this...
Thank you!
private void Form1_Load(object sender, EventArgs e)
{
Dictionary<string, DateTime> scoreList = new Dictionary<string, DateTime>();
string path = #"list.txt";
var query = (from line in File.ReadAllLines(path)
let values = line.Split(',')
select new { Key = values[0], Value = values[1] });
foreach (KeyValuePair<string, DateTime> pair in scoreList)
{
scoreList.Add(values[0], values[1]);
}
textBox1.Text = scoreList.Keys.ToString();
}
Your values variable are only in scope within the LINQ query. You need to enumerate the query result, and add the values to the dictionary:
foreach (var pair in query)
{
scoreList.Add(pair.Key, pair.Value);
}
That being said, LINQ features a ToDictionary extension method that can help you here. You could replace your loop with:
scoreList = query.ToDictionary(x => x.Key, x => x.Value);
Finally, for the types to be correct, you need to convert the Value to DateTimeusing, for instance, DateTime.Parse.
First you are doing it wrong, you should add item from list not values[0] and values[1] used in LINQ..
Dictionary<string, DateTime> scoreList = new Dictionary<string, DateTime>();
string path = #"list.txt";
var query = (from line in File.ReadAllLines(path)
let values = line.Split(',')
select new { Key = values[0], Value = values[1] });
foreach (var item in query) /*changed thing*/
{
scoreList.Add(item.Key, DateTime.Parse(item.Value)); /*changed thing*/
}
textBox1.Text = scoreList.Keys.ToString();
The immediate problem with the code is that values only exists in the query expression... your sequence has an element type which is an anonymous type with Key and Value properties.
The next problem is that you're then iterating over scoreList, which will be empty to start with... and there's also no indication of where you plan to convert from string to DateTime. Oh, and I'm not sure whether Dictionary<,>.Keys.ToString() will give you anything useful.
You can build the dictionary simply enough though:
var scoreList = File.ReadLines(path)
.Select(line => line.Split(','))
.ToDictionary(bits => bits[0], // name
bits => DateTime.ParseExact(bits[1], // date
"yyyy-MM-dd",
CultureInfo.InvariantCulture));
Note the use of DateTime.ParseExact instead of just DateTime.Parse - if you know the format of the data, you should use that information.
Going nuts over this.
Simple query but its just not working.
I simply need to get the company units that are not currently assigned to any users.
IDs are GUID type.
When debugging I see that there are 2 objects in companyUnits and 1 in userCompanyUnits.
I'm trying to get that 1 companyUnit ( that doesn't exist in userCompanyunit) to show.
Instead I get no results back.
Any idea what's wrong with the query? Maybe i can't compare based on guids ?
var companyUnitsList = from x in companyUnits
where !(from c in userCompanyUnits
select c.CompanyUnit.Id).Contains(x.Id)
select x;
Thanks in advance !
Here's a way of doing it without using the Except operator, and needing a custom IEqualityComparer:
List<Tuple<int, string>> allUnits = new List<Tuple<int, string>>();
allUnits.Add(new Tuple<int, string>(1, "unit1"));
allUnits.Add(new Tuple<int, string>(2, "unit2"));
allUnits.Add(new Tuple<int, string>(3, "unit3"));
List<Tuple<int, string>> assignedUnits = new List<Tuple<int, string>>();
assignedUnits.Add(new Tuple<int, string>(2, "unit2"));
var unassigned = allUnits.Where(m => !assignedUnits.Any(asgn => asgn.Item1 == m.Item1));
//Yields unit1 and unit3
Item1 corresponds to Unit.ID
Since you have it tagged as sql, I'm assuming this is queryable's and running against the database. Depending on the ORM and whether you have navigation properties defined and usable, you could do:
var notAssigned =
from x in companyUnits
where x.Users.Any() == false
select x;
IOW, whatever navigation property or collection exists to tie the company unit to the assigned user(s) is what you would use in the query (and would most likely translate to a sql 'exists')
var list1 = from s in new String[] {"ABC1","ABC2", "ABC3", "ABC4"} select new {Field1=s,Id = Guid.NewGuid().ToString()} ;
var list2 = new String[] {"ABC3","ABC4", "ABC5", "ABC6"} ;
var requiredList = (from i1 in list1
from i2 in list2
where !i1.Field1.Contains(i2)
select i1).Distinct();
I have a following hash table:
private Hashtable Sid2Pid = new Hashtable();
Sid2Pid.Add(1,10);
Sid2Pid.Add(2,20);
Sid2Pid.Add(3,20);
Sid2Pid.Add(4,30);
Now how to get the list of keys from the above hashtable that has a value of 20 using LinQ
Use a Dictionary<int, int> instead of a Hashtable (see here for why) then do the following:
var keys = Sid2Pid.Where(kvp => kvp.Value == 20)
.Select(kvp => kvp.Key);
A HashTable is IEnumerable of DictionaryEntry, with a little casting this can be converted into something the LINQ operators can work on:
var res = from kv in myHash.Cast<DictionaryEntry>
where (int)kv.Value = targetValue
select (int)kv.Key;
NB. This will throw an exception if you pass different types.
Is there a built-in function for converting a string array into a dictionary of strings or do you need to do a loop here?
Assuming you're using .NET 3.5, you can turn any sequence (i.e. IEnumerable<T>) into a dictionary:
var dictionary = sequence.ToDictionary(item => item.Key,
item => item.Value)
where Key and Value are the appropriate properties you want to act as the key and value. You can specify just one projection which is used for the key, if the item itself is the value you want.
So for example, if you wanted to map the upper case version of each string to the original, you could use:
var dictionary = strings.ToDictionary(x => x.ToUpper());
In your case, what do you want the keys and values to be?
If you actually just want a set (which you can check to see if it contains a particular string, for example), you can use:
var words = new HashSet<string>(listOfStrings);
You can use LINQ to do this, but the question that Andrew asks should be answered first (what are your keys and values):
using System.Linq;
string[] myArray = new[] { "A", "B", "C" };
myArray.ToDictionary(key => key, value => value);
The result is a dictionary like this:
A -> A
B -> B
C -> C
IMO, When we say an Array we are talking about a list of values that we can get a value with calling its index (value => array[index]), So a correct dictionary is a dictionary with a key of index.
And with thanks to #John Skeet, the proper way to achieve that is:
var dictionary = array
.Select((v, i) => new {Key = i, Value = v})
.ToDictionary(o => o.Key, o => o.Value);
Another way is to use an extension method like this:
public static Dictionary<int, T> ToDictionary<T>(this IEnumerable<T> array)
{
return array
.Select((v, i) => new {Key = i, Value = v})
.ToDictionary(o => o.Key, o => o.Value);
}
If you need a dictionary without values, you might need a HashSet:
var hashset = new HashSet<string>(stringsArray);
What do you mean?
A dictionary is a hash, where keys map to values.
What are your keys and what are your values?
foreach(var entry in myStringArray)
myDictionary.Add(????, entry);
I'll assume that the question has to do with arrays where the keys and values alternate. I ran into this problem when trying to convert redis protocol to a dictionary.
private Dictionary<T, T> ListToDictionary<T>(IEnumerable<T> a)
{
var keys = a.Where((s, i) => i % 2 == 0);
var values = a.Where((s, i) => i % 2 == 1);
return keys
.Zip(values, (k, v) => new KeyValuePair<T, T>(k, v))
.ToDictionary(kv => kv.Key, kv => kv.Value);
}
Dictionary<int, string> dictionaryTest = new Dictionary<int, string>();
for (int i = 0; i < testArray.Length; i++)
{
dictionaryTest.Add(i, testArray[i]);
}
foreach (KeyValuePair<int, string> item in dictionaryTest)
{
Console.WriteLine("Array Position {0} and Position Value {1}",item.Key,item.Value.ToString());
}
The Question is not very clear, but Yes you can convert a string to Dictionary provided the string is delimited with some characters to support Dictionary<Key,Value> pair
So if a string is like a=first;b=second;c=third;d=fourth you can split it first based on ; then on = to create a Dictionary<string,string> the below extension method does the same
public static Dictionary<string, string> ToDictionary(this string stringData, char propertyDelimiter = ';', char keyValueDelimiter = '=')
{
Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
Array.ForEach<string>(stringData.Split(propertyDelimiter), s =>
{
if(s != null && s.Length != 0)
keyValuePairs.Add(s.Split(keyValueDelimiter)[0], s.Split(keyValueDelimiter)[1]);
});
return keyValuePairs;
}
and can use it like
var myDictionary = "a=first;b=second;c=third;d=fourth".ToDictionary();
since the default parameter is ; & = for the extension method.
You can create a dictionary from an IEnumerable<T>, including an array, via:
var dictionary = myEnumerable.ToDictionary(element => element.Key,
element => element.Value)
where Key and Value are the key and value you want to store in each dictionary element. Available in .NET Framework 3.5+/.NET Core 1.0+/.NET 5.0+. Official documentation.
If you want the dictionary values to be the elements from the original enumerable:
var dictionary = myEnumerable.ToDictionary(element => element.Key)
If you only need high-performance set operations, you may be able to use:
var words = new HashSet<string>(listOfStrings);
In simple terms, the HashSet class can be thought of as a Dictionary<TKey,TValue> collection without values. Official documentation.
(Note that a 'sequence' in an entirely unrelated object.
Originally submitted an existing answer edit but it was rejected by the author so posting separately, including with links to the official Microsoft documentation.)