C# Get Keys from a Dictionary<string, Stream> - c#

Suppose I have a Dictionary like so:
Dictionary<string, Stream>
How can I get a list (or IEnumerable or whatever) of JUST the Keys from this dictionary? Is this possible?
I could enumerate the dictionary, and extract the keys one by one, but I was hoping to avoid this.
In my instance, the Dictionary contains a list of filenames (file1.doc, filex.bmp etc...) and the stream content of the file from another part of the application.

KeyCollection Dictionary(TKey, TValue).Keys

Dictionary(TKey, TValue).Keys
Typically you can discover these things through code-completion/IntelliSense.
Similarly, there is a Values property:

Dictionary<T,T>.Keys returns a KeyCollection. This has the IEnumerable interface.
so...
foreach(string key in Dictionary<string,Stream>.Keys)
{
}

public IEnumerable<long> ReturnSomeKeys()
{
var foo = new Dictionary<long, string>();
return foo.Keys;
}
This does what you want.

Related

C# Remove item from nested dictionary

I've got a simple question that my mind is drawing a blank to: I have a Dictionary that looks something like this:
Dictionary<string, Dictionary<string, string>> dict;
As far as I know, dict.Remove() would remove any entry by key, but I need to only remove an item from the innermost dictionary. How would I go about that?
Well presumably you've got two keys: one for the outer dictionary and one for the nested one.
So assuming you know that the entry is present, you can use
dict[outerKey].Remove(innerKey);
If you don't know whether the entry exists, you want something like:
Dictionary<string, string> innerDict;
if (dict.TryGetValue(outerKey, out innerDict))
{
// It doesn't matter whether or not innerKey exists beforehand
innerDict.Remove(innerKey);
}
If you just have the inner key, you can do something like this:
string removeKey = "42";
Dictionary<String, String> removeDict = dict.Select(d=> d.Value).FirstOrDefault(d => d.ContainsKey(removeKey));
if(removeDict !=null)
removeDict.Remove(removeKey);
In this implementation if there is more then one register with the same innerKey just the first occurrence will be removed
Try
dict["key"].Remove("childkey");
Notice the keys are string values.

What type is the best for loose numerically-indexed lists in C#?

What I need is something like an array but letting me to assign an element to whatever an index at any time and check if there is already a value assigned to particular index approximately like
MyArray<string> a = new MyArray<string>();
a[10] = "ten";
bool isTheFifthElementDefined = a[5] != null; // false
Perhaps Dictionary<int, string> with its ContainsKey method could do, but isn't there a more appropriate data structure if I want an ordered collection with numeric keys only?
I am also going to need to iterate through the defined elements (with foreach or linq preferably) accessing both the value and the key of current element.
As you mentioned Dictionary seems more appropriate for this.But you can do it with generic lists,for example, when you are creating your list you can specify an element count,and you can give a default temporary value for all your elements.
List<string> myList = new List<string>(Enumerable.Repeat("",5000));
myList[2300] = "bla bla bla..";
For int:
List<int> myList = new List<int>(Enumerable.Repeat(0,5000));
For custom type:
List<MyClass> myList = new List<MyClass>(Enumerable.Repeat(new MyClass(), 100));
Ofcourse It is not the best solution...
Note: Also you can use SortedList instead of Dictionary if you want an ordered collection by keys:
SortedList<TKey, TValue> : Represents a collection of key/value pairs that are sorted by key based on the associated IComparer implementation.
If you need key/value pairs you cannot use a list, you'll need a Dictionary.
The implementation is pretty snappy so don't be too afraid about performance (as long as you don't put too much values in it).
You can iterate over it with
foreach(KeyValuePair<int, string> kvp in dict)
{
}
If you need to order it you can use a list:
List<int> ordered = new List(dict.Keys);
ordered.Sort();
foreach(int key in ordered)
{
}

increasing dimensions in a list

using ...
string[] myFiles = Directory.GetFiles(FilePathIn, "*.dat", SearchOption.TopDirectoryOnly);
I am getting a list of files returned. Alongside this I want to keep a set of int flags. I am about to do this by creating a tuple list eg List<Tuple<int, string>> then looping through myfiles adding each to the tuple list.
Although this will work I wondered if there was a cleaner way to do this? It doesn't have to be a tuple list. It just needs to be an ordered list of the files with a flag
If you are interested in just iteration then a list of some compound type is the way to go -- you can use a custom struct instead of a Tuple to increase readability or a custom class if you intend for the flags to be mutable later on, but the general idea is the same.
You can also use a Dictionary<string, int> of filenames to flags; this has the advantage that it allows quick lookups if you have a filename in hand.
Finally, consider using a [Flags] enum instead of a bare integer to hold the flags you need.
Depending on how you want to use the data later, I would either map the filenames to the integers (Dictionary<string, int>) or the integers to files. I assume two files can have the same "flag", so I would use either a Dictionary<int, List<string>> or constuct IGrouping<int, string> or ILookup<int, string>. It's a shame really that .NET BCL doesn't contain a straightforward mutable Multimap (or Lookup) that you could use like a dictionary.
Why you don't use dictionary to access an element in a dictionary it will cost O(1)
Dictionary<int,string> myFilesOrderedDict = new Dictionary<int,string>();
Or if you want to groupfile by an int as a flag you can do the inverse as I don't think that the name of the file can be repeated twice
Something like this
//string will be the name of the file
Dictionary<string ,int> myFilesOrderedDict = new Dictionary<string,int>();
Hope this help
You can create an anonymous type:
var filesWithFlags = Directory.GetFiles(..)
.Select(f => new {File = f, Flags = 123});
And use the result like this:
foreach (var fileWithFlags in filesWithFlags)
{
DoSomethingWith(fileWithFlags.File);
AndDoSomethingWith(fileWithFlags.Flags);
}

Is there something like the .NET Dictionary with duplicated keys to fill with a text file?

I have a text file with the following structure
01|value|value|value|value|value|value
02|value|value|value|value|value|value
03A|value|value|value|value|value|value
03A|value|value|value|value|value|value
.
.
N
04|value|value|value|value|value|value
05|value|value|value|value|value|value
06|value|value|value|value|value|value
.
.
N (variable lines)
I tried to read the text file and add it to a dictionary of type <string, string[]> in order to use it like MyDic["01"][0], this is a fragment of the code:
Dictionary<string, string[]> txtFromFile= new Dictionary<string, string[]>();
string strLine;
using (StreamReader sr = new StreamReader(filePath))
{
while ((strLine= sr.ReadLine()) != null)
{
string[] strNodes= strLine.Split('|');
txtFromFile.Add(strNodes[0], strNodes);
}
}
Unfortunately, as you can see, this text file could have duplicated keys like 03A, so I was wondering if there's a collection in c# to achieve this.
NOTE I saw a class named lookup, but there's no constructor for it.
Any thoughts my friends?
What do you suggest?
Thanks!
Why not just create a class like
public class MyLine
{
string key { get;set;}
string[] value {get;set;}
}
and store it in a geneirc List
then you can use linq to query whatever you want ...
You can use the ToLookup extension method:
string[] lines = File.ReadAllLines(filePath);
ILookup<string, string[]> result = lines
.Select(line => line.Split('|'))
.ToLookup(parts => parts[0]);
The first problem is that you are trying to use the wrong type, if you are concerned with multiple entries with the same key. You can achieve this with a List<KeyValuePair<string, string[]>> and your own lookup function, likely through extending the class, or you can add another dictionary inside the dictionary as your value type: Dictionary<string, Dictionary<int, string[]>>. The Dictionary option is the better bet as it has better performance.
How about a List with a custom type?
class KeyValue
{
String ID { get ; set ; }
List<String> Values { get ; private set ;}
(..Constructor etc...)
}
List<KeyValue> myValues = new List<KeyValue>();
while ((strLine= sr.ReadLine()) != null)
{
string[] strNodes= strLine.Split('|');
myValues.Add(new KeyValue(strNodes[0],strNodes));
}
You could use List<KeyValuePair<string, string[]>> or List<Tuple<string, string[]>>
(And of course you might prefer a different collection type instead of List<>)
I'm not sure if you're trying to distinguish between values on the first 03A line from values on the second 03A line, but I think you're looking for a NameValueCollection. NameValueCollections allow you to add multiple values to the same key, and the Add() method should check for pre-existing keys before appending the values/creating a new key/value entry.
There's a good example of the way to use the NameValueCollection at the bottom of that MSDN reference article, so you should be able to use that to determine if it's what you really need.
Another thought would be to use
Dictionary<string, List<string[]>>
Where "string" is the value that might be repeated. When it gets repeated, you create another Dictionary inside. If a row exists once, it will have one List. If a duplicate row is found, add another. In this way, you can see how many duplicate rows there were just by count of Lists.

Using LINQ to find all keys from one collection that are not in another?

I'm trying to locate all the keys in one Dictionary that are not in another Dictionary. Obviously, I can do this using a nested loop, but I'm trying to learn LINQ at the moment and I was wondering if I might use it to accomplish this task?
Here's what I have so far:
Dictionary<string, List<string>> DBtables = this.CollectTableListings();
var generic = from Dictionary<string,List<string>> tab
in DBtables
where !_tables.ContainsKey(???)
select tab;
Any idea what should go in place of the question marks (or perhaps instead of the entire where clause)?
You can do:
var resultKeys = DBTables.Keys.Except( _tables.Keys );
The Except() method is essentially the same as the minus operations in SQL - it returns all items from the first collection excluding those in the second. Since dictionaries expose their keys, you can compute their difference that way.
The Except() operator uses the default equality for the type, but there is also an overload which allows you to specify your own IEqualityComparer to override the semantics of how to compare values. In your example, you probably don't need that - but it's nice to know it there.
Dictionary<string, List<string>> dictOne = ...
Dictionary<string, List<string>> dictTwo = ...
var missingKeys = dictOne.Keys.Where(x => !dictTwo.ContainsKey(x));
Dictionary<string, List<string>> dictionary = this.CollectTableListings();
Dictionary<string, List<string>> otherDictionary = getOtherTable();
var keys = from key in dictionary.Keys
where !otherDictionary.Keys.Contains(key)
select key;
(But LBuskin's answer is much better)
have a look at the Except extension method. HTH.
If you wanted to use query syntax I would do something akin to below:
var keys = from d1 in dictionary1
select d1.Key;
var items = from d2 in dictionary2
where d2.Key in keys
select d2;
foreach(var item in items)
{
}

Categories