How to swap Hashtable's key with Value - c#

I have solved it by following.
Since it is long, i need a better one.
//Code
class Program
{
static void Main(string[] args)
{
Hashtable hsTbl = new Hashtable();
hsTbl.Add(1, "Suhas");
hsTbl.Add(2, "Madhuri");
hsTbl.Add(3, "Om");
List<object> keyList = new List<object>();
List<object> ValList = new List<object>();
Console.WriteLine("Key Value");
foreach (DictionaryEntry item in hsTbl)
{
Console.WriteLine(item.Key + " " + item.Value);
keyList.Add(item.Value);
ValList.Add(item.Key);
}
hsTbl.Clear()
//Swapping
for (int i = 0; i < keyList.Count; i++)
{
hsTbl.Add(keyList[i], ValList[i]);
}
//will display hashtable after swapping
foreach (DictionaryEntry item in hsTbl)
{
Console.WriteLine(item.Key + " " + item.Value);
}
}
}
Is there any other better solution?

You could do it slightly simpler using an additional array and the CopyTo method rather than 2 lists but without creating an additional HashTable as follows:
//Code
using System;
using System.Collections;
class Program
{
static void Main()
{
Hashtable hsTbl = new Hashtable();
hsTbl.Add(1, "Suhas");
hsTbl.Add(2, "Madhuri");
hsTbl.Add(3, "Om");
DictionaryEntry[] entries = new DictionaryEntry[hsTbl.Count];
hsTbl.CopyTo(entries, 0);
hsTbl.Clear();
foreach(DictionaryEntry de in entries) hsTbl.Add(de.Value, de.Key);
// check it worked
foreach(DictionaryEntry de in hsTbl)
{
Console.WriteLine("{0} : {1}", de.Key, de.Value);
}
}
}
Note that, in general, no method is guaranteed to work because some of the values in the original hashtable may be duplicated and therefore be unsuitable as keys.

You can use generic Dictionary<string,int>, which is easy to create with Linq:
var dictionary = hsTbl.OfType<DictionaryEntry>()
.ToDictionary(e => (string)e.Value, e => (int)e.Key);
If you really need Hashtable, then:
Hashtable table = new Hashtable();
foreach (DictionaryEntry entry in hsTbl)
table.Add(entry.Value, entry.Key);
But make sure that all values are unique, if you want to swap value and key.

Related

loading data from csv file into key and value dictionary list

I have a file consisting of a list of text which looks as follows:
Example csv file
There csv file has consist of 3 columns. The first columns will always be the length of 5. So I want to loop through the file content, store those first 5 letters as Key and remaining column as value. I am removing comma between them and Substringing as follows to store.
static string line;
static Dictionary<string, string> stations = new Dictionary<string, string>();
static void Main(string[] args)
{
// Dictionary<string, List<KeyValuePair<string, string>>> stations = new Dictionary<string, List<KeyValuePair<string, string>>>();
var lines = File.ReadAllLines(".\\ariba_sr_header_2017122816250.csv");
foreach (var l in lines)
{
line = l.Replace(",", "");
stations.Add(line.Substring(14),line.Substring(14, line.Length-14));
}
//read all key and value in file
foreach (KeyValuePair<string, string> item in stations)
{
Console.WriteLine(item.Key);
Console.WriteLine(item.Value);
}
Console.ReadLine();
}
After debug, the output is
Output
My Expected Result is as follow:
Expected Result
I cannot see any KeyValuePair here. You have
00021,00014,Ordered
00021,00026,Ordered
00024,00036,Ordered
...
and you want
00021
00021
00024
000014Ordered
000026Ordered
000036Ordered
...
outcome which seems to be IEnumerable<string>. You can try Linq for this
var result = File
.ReadLines(".\\ariba_sr_header_2017122816250.csv")
.Line(line => line.Split(','))
.SelectMany(items => new string[] {
items[0],
$"0{items[1]}{items[2]}" })
.OrderBy(item => item.Length);
foreach (var item in result)
Console.WriteLine(item);
Here we Split each line like 00021,00014,Ordered into separate items: {00021, 00014, Ordered}anf then combine them back with a help ofSelectMany`. We want
00021 which is items[0]
000014Ordered which is 0 + items[1] + items[2]
Finally we want to have short items first - OrderBy(item => item.Length)
Here you go:
var stations = new Dictionary<string, string>();
var lines = File.ReadAllLines(#"C:\temp\22.txt");
foreach (var l in lines)
{
var lsplit = l.Split(',');
if (lsplit.Length > 1)
{
var newkey = lsplit[0];
var newval = lsplit[1] + lsplit[2];
stations[newkey] = newval;
}
}
//read all key and value in file
foreach (KeyValuePair<string, string> item in stations)
{
Console.WriteLine(item.Key + " = " + item.Value);
}
Console.ReadLine();
Not exactly the output you expected, but hopefully it helps.

Unable to find value by key in dictionary in case of comma separated key

I have a dictionary like below where i store list of file names with key generated as Csv1,Csv2 based on number of files.
I have a string array like below :
string[] files = { "SampleCSVFile_5300kb1.csv,SampleCSVFile_5300kb2.csv", "SampleCSVFile_5300kb3.csv"};
int counter=1;
var dictionary = new Dictionary<string, string>();
foreach (var file in files)
{
dictionary.Add("CSV" + counter, file);
counter++;
}
foreach (var file in files)
{
string myValue;
if (dictionary.TryGetValue(file, out myValue)) // getting null in out value
}
When i try to search for SampleCSVFile_5300kb1.csv i am getting null in my myValue variable.
Screenshot:
Update:i realize that i was adding wrong key so changed it like below but still unable to find CSV1 in case of SampleCSVFile_5300kb1.csv:
foreach (var file in files)
{
dictionary.Add(file,"CSV" + counter);
counter++;
}
Based on the comment you said in Amir Popoviches answer. I think you should alter your dictionary construction.
So you will create a mapping from each of the .csv file(s) to the "CSV1" etc string.
var files = new[] { "SampleCSVFile_5300kb1.csv,SampleCSVFile_5300kb2.csv", "SampleCSVFile_5300kb3.csv" };
var counter = 1;
var dictionary = new Dictionary<string, string>();
foreach (var file in files)
{
if (string.IsNullOrWhiteSpace(file))
{
continue;
}
foreach (var item in file.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
{
dictionary.Add(item, "CSV" + counter);
}
counter++;
}
And as you said in comments you want to find what "CSVX" file is for each of the files you have so we simulate you trying to find a match for these files. Notice that this array has all separate file names, in the upper array we had values comma separated so we group them together.
var files2 = new[] { "SampleCSVFile_5300kb1.csv", "SampleCSVFile_5300kb2.csv", "SampleCSVFile_5300kb3.csv" };
foreach (var file in files2)
{
string csvValue;
if (dictionary.TryGetValue(file, out csvValue))
{
Console.WriteLine("{0} -> {1}", file, csvValue);
}
}
This should output you
SampleCSVFile_5300kb1.csv -> CSV1
SampleCSVFile_5300kb2.csv -> CSV1
SampleCSVFile_5300kb3.csv -> CSV2
First argument in TryGetValue is key. So you should pass there "CSV" + counter to make it works.
https://msdn.microsoft.com/pl-pl/library/bb347013(v=vs.110).aspx
You are adding items to the dictionary with the following keys:
"CSV" + counter -> CSV1, CSV2...
And you are trying to find different values (e.g. "SampleCSVFile_5300kb1.csv,SampleCSVFile_5300kb2.csv") here:
foreach (var file in files)
{
string myValue;
if (dictionary.TryGetValue(file, out myValue)) // getting null in out value
}
Try below updated code:
string[] files = { "SampleCSVFile_5300kb1.csv,SampleCSVFile_5300kb2.csv", "SampleCSVFile_5300kb3.csv" };
int counter = 1;
var dictionary = new Dictionary<string, string>();
foreach (var file in files)
{
dictionary.Add("CSV" + counter, file);
counter++;
}
counter = 1;
foreach (var file in files)
{
string myValue;
//You need to pass key name here but you are passing value of it
//Need to update here
string keyName = "CSV" + counter;
if (dictionary.TryGetValue(keyName, out myValue)) ; // getting null in out value
counter++;
}
Iterate the dictionary an find your desired value using split by comma. you will get "SampleCSVFile_5300kb1.csv" and "SampleCSVFile_5300kb2.csv" into the fileName array for the same myvalKey
foreach (KeyValuePair<string, string> entry in dictionary)
{
string myvalKey = entry.Key;
string myval = entry.Value;
if (myval.Contains(',')) {
string[] fileNames = myval.Split(',');
}
}
From what I understand you seem to be looking for a way to match only part of a key. And while I suggest using the answers of Janne Matikainen and just add the parts of your key separately with the same value, regardless I will give you a way to match on a partial key using a bit of Linq.
string resultValue = null;
string resultKey = dictionary.Keys.FirstOrDefault(k => k.Contains(file));
if(resultKey != null)
resultValue = dictionary[resultKey];
this does assume only the first match is wanted, if you want all matching keys replace FirstOrDefault with Where.
Beware that while this code is easy it is not suitable for when performance is critical as you iterate over the keys basically using the dictionary as a
List<Tuple<string,string>>

How to add dynamic member name and value to an instance of ExpandoObject class?

Let’s say list of member names stored in an array like below,
string[] myMembers = { "ChapterName", "Medium", "LastName", "OrderID" };
I wrote the following code to generate dynamic class and members along with random values.
var myDynamicClassList = new List<ExpandoObject>();
foreach (var MemberName in myMembers)
{
dynamic dynamicClass = new ExpandoObject();
dynamicClass.MemberName = new Random().Next();
myDynamicClassList.Add(dynamicClass);
}
In order to display output of the above myDynamicClassList I wrote the following code.
foreach (var x in myDynamicClassList)
{
foreach (var property in (IDictionary<String, Object>)x)
{
Console.WriteLine(property.Key + ": " + property.Value);
}
}
Showing output like this
MemberName : 123465461
MemberName : 564613611
MemberName : 134654321
MemberName : 786451214
But Instead of above output I am expecting the output like below
ChapterName : 123465461
Medium : 564613611
LastName : 134654321
OrderID : 786451214
Here is my question, is it possible to add dynamic member name to a dynamic class in c#. If it is possible please let me know, if not please guide me to complete this job.
I really appreciate your help in advanced.
As described in a similar question ("Dynamically adding properties to an ExpandoObject"), you can do this by using IDictionary directly:
string[] myMembers = { "ChapterName", "Medium", "LastName", "OrderID" };
var myDynamicClassList = new List<ExpandoObject>();
Random random = new Random();
foreach (var MemberName in myMembers)
{
IDictionary<string, object> dynamicClass = (IDictionary<string, object>)(new ExpandoObject());
dynamicClass.Add(MemberName, random.Next());
myDynamicClassList.Add((ExpandoObject)dynamicClass);
}
foreach (var x in myDynamicClassList)
{
foreach (var property in (IDictionary<String, Object>)x)
{
Console.WriteLine(property.Key + ": " + property.Value);
}
}
However, you should be aware of possible known memory limitations with this method as described in the comments of the post linked above, or in the Microsoft issue. I would possibly rethink the design to consider what properties are actually needed, or simply using a Dictionary if it's feasible (to avoid the dynamic ExpandoObject entirely).
I also moved your Random outside of the loop. Creating new instances of Random inside a loop may not give you the results you expect...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.IO;
namespace Deligate
{
class Program
{
public static List<Employee> empList = new List<Employee>();
public static void UserInfo(int val)
{
Employee emp = new Employee();
Console.WriteLine($"Enter {val+1} Employee Details :- ");
Console.WriteLine("Enter Your Name: ");
emp.Name= Console.ReadLine();
Console.WriteLine("Enter your Email: ");
emp.Email = Console.ReadLine();
Console.WriteLine("Enter Mobile Number");
emp.Mobile = Console.ReadLine();
empList.Add(emp);
}
public static void CountEmp()
{
Console.WriteLine("How many user you want to add:");
var UserCount = int.Parse(Console.ReadLine());
for (int i = 0; i < UserCount; i++)
{
UserInfo(i);
}
foreach (var employee in empList) {
Console.WriteLine(employee.Name+ ", " + employee.Email+", "+employee.Mobile);
}
System.IO.File.Delete(#"D:\Compare.txt");
foreach (var el in empList)
{
System.IO.File.AppendAllText(#"D:\Compare.txt", el.Name+", "+el.Email+", "+el.Mobile + Environment.NewLine);
}
}
public static void Main(string[] args)
{
CountEmp();
Console.ReadKey();
}
}
}

How to print contents of an hash table?

I've an hash table with the details as mentioned below
public void get_Unique_Sequence(List<string> name, List<List<string>> nameSequence)
{
Hashtable test = new Hashtable();
test.Add(nameSequence, name)
foreach (DictionaryEntry entry in test)
{
Console.WriteLine("{0}: {1}", entry.Key, entry.Value);
}
}
I'm trying to print the contents of the hash table with the help of foreach loop. However the output which I'm getting is
output:
System.Collections.Generic.List`1[System.String]: System.Collections.Generic.List`1[System.String]
Please guide me to get the key and value (that is the contents) of the hashtable.
You probably don't want to insert the lists objects in the hash table, but the elements in the list.
So first you have to do something like:
(assuming that the list are not null and have the same size)
for(int i =0;i<name.Count;i++){
test.Add(nameSequence[i], name[i]);
}
instad of:
test.Add(nameSequence, name);
And then your method should work.
I don't know how you would like to format the output, but to print the content of a List you have to iterate on it.
On the List of lists you need to iterate two times.
Maybe a solution could be this:
public void get_Unique_Sequence(List<string> name, List<List<string>> nameSequence)
{
Hashtable test = new Hashtable();
test.Add(nameSequence, name);
foreach (DictionaryEntry entry in test)
{
string key = string.Empty;
foreach (string s in (List<string>)entry.Key)
{
key += s + " ";
}
foreach (List<string> list in (List<List<string>>)entry.Value)
{
string value = string.Empty;
foreach (string s in list)
{
value += s + " ";
}
Console.WriteLine("{0}: {1}", key, value);
}
}
}
Of course, you need to format the output according to your needs.
Well, the issue isn't about printing the hashtable. It's about printing a List<List<string>>.
You want something like this for each key and value:
foreach (var sublist in result)
{
foreach (var obj in sublist)
{
Console.WriteLine(obj);
}
}

Converting a string to a variable name

public static string filename2_1, filename2_2, filename2_3;
filename2_1="xyz.jpg";
filename2_2="abc.png";
filename2_3="qwe.jpg";
.....
...
for (int key = 1; key <= 3; key++)
{
....
foreach (var item in tabItem)
{
item.ImagePath.Value = "images1/" + ("filename2_" + key);
item.ThumbPath.Value = "thumbnails1/" + ("filename2_" + key);
}
}
As stated above I need to convert ("filename2_" + key) into actual variable. Can anyone help me regarding this
You can't have dynamic variable names.
Variable names cannot be "created".
You can use an array or a generic collection to hold the collections of data you are using.
var fileSuffixList = new List<string>{ "xyz.jpg" , "abc.png", "qwe.jpg"};
foreach(string fileSuffix in fileSuffixList)
{
....
foreach (var item in tabItem)
{
item.ImagePath.Value = "images1/" + ("filename2_" + fileSuffix);
item.ThumbPath.Value = "thumbnails1/" + ("filename2_" + fileSuffix);
}
}
As #Oded stated, you can't have dynamic variable names.
What you can do is use a Collection such as a dictionary:
Dictionary<string, int> dictionary = new Dictionary<string, string>();
dictionary.Add("filename2_" + key, "Value");
If your keys are always numeric, you can also use an array or a List. However, without more information, it's hard to tell you the best way to go about it.

Categories

Resources