I have 2 dictionaries with the same keys but different values. I need to find in dictionary1 all values that are equal to 1 and replace them with the value in dictionary2. I could edit the first dictionary or better idea is to save the new values into another dictionary either way is fine. My idea was to use a foreach loop and then find any values in dictionary1 == 1 then go inside dictionary2 and extract that value for that key and save it into dictionary1 or another dictionary for that key.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Practice_With_Dictionaries
{
class Program
{
static void Main(string[] args)
{
object[] keys= new object[5];
keys[0] = "1111";
keys[1] = "2222";
kesy[2] = "3333";
kesy[3] = "4444";
kesy[4] = "5555";
object[] speed = new object[5];
speed[0] = 1;
speed[1] = 2;
speed[2] = 1;
speed[3] = 1;
speed[4] = 5;
object[] speed2 = new object[5];
speed2[0] = 1;
speed2[1] = 2;
speed2[2] = 3;
speed2[3] = 4;
speed2[4] = 5;
Dictionary<object, object> dictionary1 = new Dictionary<object,object>();
Dictionary<object, object> dictionar2 = new Dictionary<object, object>();
for (int iRow = 0; iRow < interfaceKeys.Length; iRow++)
{
dictionary1.Add(keys[iRow], (double)speed[iRow]);
dictionary2.Add(keys[iRow], (double)speed2[iRow]);
}
// for each loop with if statements
}
}
}
First of all, if you have string as key, and int as value, then you should use Dictionary<string, int> instead of Dictionary<object, object>.
Dictionary<string, int> dictionary1 = new Dictionary<string, int>();
Dictionary<string, int> dictionary2 = new Dictionary<string, int>();
// fill your dictionaries
Now if you always have matching keys between two dictionaries:
var keys = dictionary1.Where(kvp => kvp.Value == 1).Select(kvp => kvp.Key);
foreach (var key in keys)
dictionary1[key] = dictionary2[key];
Otherwise
var keys = dictionary1.Where(kvp => kvp.Value == 1).Select(kvp => kvp.Key);
foreach (var key in keys)
{
int value;
if (dictionary2.TryGetValue(key, out value))
dictionary1[key] = value;
}
You can use LINQ and the ToDictionary method (I made some changes to simplify your code, I hope this is acceptable):
static void Main(string[] args)
{
var keys = new string[5] { "1111", "2222", "3333", "4444", "5555" };
var speed = new double[5] { 1, 2, 1, 1, 5 };
var speed2 = new double[5] { 1, 2, 3, 4, 5 };
var dictionary1 = new Dictionary<string, double>();
var dictionary2 = new Dictionary<string, double>();
for (int iRow = 0; iRow < keys.Length; iRow++)
{
dictionary1.Add(keys[iRow], speed[iRow]);
dictionary2.Add(keys[iRow], speed2[iRow]);
}
// the solution
var result = dictionary1.ToDictionary(x => x.Key, kv => kv.Value == 1 ? dictionary2[kv.Key] : kv.Value);
}
you could do something like this
var dictionary1 = new Dictionary<string, string>
{
{"a", "1"},
{"b", "2"},
{"c", "3"},
{"d", "3"}
};
var dictionary2 = new Dictionary<string, string>
{
{"a", "1"},
{"b", "22"},
{"c", "33"}
};
var result = dictionary1
.Where(d => dictionary2.ContainsKey(d.Key) && dictionary2[d.Key] == d.Value);
result will contain all values that have same keys in dictinary1 and dictinary2 with values in dictinary1.
Related
I am trying to converting from dictionary to list while converting I am getting the output
I/p-
dic.Add("Demo1",2);
dic.Add("Demo2",1);
dic.Add("Demo3",1);
dic.Add("Demo4",2);
O/p-
Demo1
Demo2
Demo3
Demo4
But I need Demo1 and Demo4 two times because their quantity are 2. So How can I achieve that??
Below is the code
public IList<string> DictionaryToList(IDictionary<string,int> dictionary)
{
IDictionary<string, int> dic = new Dictionary<string, int>();
IList<string> lst = new List<string>();
dic.Add("Demo1",2);
dic.Add("Demo2",1);
dic.Add("Demo3",1);
dic.Add("Demo4",2);
foreach (var item in dic)
{
if (!lst.Contains(item.Key))
{
lst.Add(item.Key);
}
}
return lst;
}
}
class Program
{
static void Main(string[] args)
{
var conversion = new Conversion();
var list = new List<string> { "Demo1","Demo2","Demo3","Demo4","Demo1","Demo4"};
var dictionary = conversion.ListToDictionary(list);
foreach (var item in dictionary)
{
Console.WriteLine($"{item.Key}, {item.Value}");
}
var convertedList = conversion.DictionaryToList(dictionary);
foreach (var item in convertedList)
{
Console.WriteLine($"{item}");
}
Console.ReadLine();
}
Thanks in advance.
You can use LINQ's SelectMany and Enumerable.Repeat:
IList<string> list = dictionary
.SelectMany(kv => Enumerable.Repeat(kv.Key, kv.Value))
.ToList();
Here is also the opposite way to build your dictionary from the list:
var list = new List<string> { "Demo1", "Demo2", "Demo3", "Demo4", "Demo1", "Demo4" };
var dictionary = list.GroupBy(s => s).ToDictionary(g => g.Key, g => g.Count());
IList<string> list2 = dictionary
.SelectMany(kv => Enumerable.Repeat(kv.Key, kv.Value))
.ToList();
So at the end list2 contains the same strings as list but in a different order.
Your dictionary consists of a key (string) and a value (int). After checking
if (!list.Contains(item.Key)) just add another loop which goes from 0 to the actual value from your dictionary-item and adds the new item n-times.
for (int i = 0; i < item.Value; i++) // Demo1 and Demo4 runs 2x, Demo2 and Demo3 1x
lst.Add(item.Key);
Do you want something like this?
Dictionary<string, int> dic = new Dictionary<string, int>();
List<string> lst = new List<string>();
dic.Add("Demo1", 2);
dic.Add("Demo2", 1);
dic.Add("Demo3", 1);
dic.Add("Demo4", 2);
foreach (var item in dic)
{
for (int i = 0; i < item.Value; i++)
{
lst.Add(item.Key);
}
}
Below is the code where key is being hard-coded in Dictionary
var datalist = new List<IDictionary<string, string>>();
for (var i = 0; i < dt.Rows.Count; ++i)
{
var data = new Dictionary<string, string>()
{
{ "ID", Convert.ToString(dt.Rows[i]["ID"]) },
{ "STATUS", Convert.ToString(dt.Rows[i]["Name"]) },
{ "TYPE", Convert.ToString(dt.Rows[i]["TYPE"]) }
};
datalist.Add(data);
}
Now, instead of hard-coding the keys like ID, STATUS, etc, I want to add it from my string array containing the values below
string[] arrNames = ConfigurationManager.AppSettings["NameKey"].Split(',');
How can I traverse arrNamesto add keys in Dictionary and then add in List?
Iterate through the collection of names:
var datalist = new List<IDictionary<string, string>>();
string[] arrNames = ConfigurationManager.AppSettings["NameKey"].Split(',');
for (var i = 0; i < dt.Rows.Count; ++i)
{
var data = new Dictionary<string, string>();
foreach (var name in arrNames)
{
data[name] = Convert.ToString(dt.Rows[i][name]);
}
datalist.Add(data);
}
your code should look something like this
var datalist = new List<IDictionary<string, string>>();
string[] arrNames = Convert.ToString(ConfigurationManager.AppSettings["NameKey"]).Split(',');
if (arrNames.Length == 3)
{
for (var i = 0; i < dt.Rows.Count; ++i)
{
var data = new Dictionary<string, string>()
{
{ arrNames[0], Convert.ToString(dt.Rows[i][arrNames[0]]) },
{ arrNames[1], Convert.ToString(dt.Rows[i][arrNames[1]]) },
{ arrNames[2], Convert.ToString(dt.Rows[i][arrNames[2]]) }
};
datalist.Add(data);
}
}
You can use linq method ToDictionary. Try this code:
string[] arrNames = // new[] {"ID", "STATUS", "TYPE"};
var datalist = new List<IDictionary<string, string>>();
for (var i = 0; i < dt.Rows.Count; ++i)
datalist.Add(
arrNames
.Select(key =>
new
{
key,
value = Convert.ToString(dt.Rows[i][key])
}
)
.ToDictionary(x => x.key, x => x.value)
);
If you prefer LINQ-y and concise you could try something like:
var names = ConfigurationManager.AppSettings["NameKey"].Split(',');
var list = dt.AsEnumerable()
.Select(r => names.ToDictionary(n => n, n => r[n]))
.ToList();
Here I'm assuming dt is a DataTable.
If you have at least the same number of items in your arrNames array than columns you want to read and of course with this order, then you can hardcore the indexes.
var datalist = new List<IDictionary<string, string>>();
for (var i = 0; i < dt.Rows.Count; ++i)
{
var data = new Dictionary<string, string>()
{
{ arrNames[0], Convert.ToString(dt.Rows[i]["ID"]) },
{ arrNames[1], Convert.ToString(dt.Rows[i]["Name"]) },
{ arrNames[2], Convert.ToString(dt.Rows[i]["TYPE"]) }
};
datalist.Add(data);
}
In a C# List>, how can I extract unique key/value pairs and store it in List>?
List<Dictionary<string,string>> md = new List<Dictionary<string,string>>();
Input
md[0] :
[0]:"A","Apple"
[1]:"B","Ball"
md[1]:
[0]:"A","Apple"
[1]:"B","Ball"
md[2]:
[0]: "C", "Cat"
[1]: "D", "Dog"
Output
md[0] :
[0]:"A","Apple"
[1]:"B","Ball"
md[1]:
[0]:"C" : "Cat"
[1]:"D" : "Dog"
Code sample to extract both unique key/value pairs are needed, only unique keys or unique values are not needed.
(* Note : [0],[1] above depicts the indexes in the list and dictionary and not the keys or values)
List<Dictionary<string,string>> md = new List<Dictionary<string,string>>();
var unique = new Dictionary<string, string>();
foreach (var m in md)
{
foreach(var innerKey in m.Key)
{
if (!unique.ContainsKey(innerKey))
{
unique.Add(innerKey, m[innerKey]);
}
}
}
One possible strictly correct solution would be to implement IEqualityComparer<Dictionary<string, string>>:
public class DictionaryComparer : IEqualityComparer<Dictionary<string, string>>
{
public int GetHashCode(Dictionary<string, string> d)
{
var hashCode = 17;
foreach (var entry in d.OrderBy(kvp => kvp.Key))
{
hashCode = hashCode * 23 + entry.Key.GetHashCode();
hashCode = hashCode * 23 + entry.Value.GetHashCode();
}
return hashCode;
}
public bool Equals(Dictionary<string, string> d1, Dictionary<string, string> d2)
{
string value2;
return d1.Count == d2.Count && d1.All(kvp => d2.TryGetValue(kvp.Key, out value2) && kvp.Value == value2);
}
}
Then to get your list of unique dictionaries:
var result = md.Distinct(new DictionaryComparer()).ToList();
You can do it with linq.
List<Dictionary<string, string>> md = new List<Dictionary<string, string>>();
md.Add(new Dictionary<string, string>() { { "A","Apple"}, { "B", "Ball" } });
md.Add(new Dictionary<string, string>() { { "A","Apple"}, { "B", "Ball" } });
md.Add(new Dictionary<string, string>() { { "C","Cat"}, { "D", "Dog" } });
var filtered =
md.GroupBy(x => string.Join("", x.Select(i => string.Format("{0}{1}", i.Key, i.Value)))).Select(x => x.First());
Variable "filtered" contains list of dictionaries with unique sets.
With LINQ I do not know how to split a list of items in two lists in which the sum of the values has the lowest gap possible while preserving the order of the input list.
Using this list as an example:
key value
A 5
B 2
C 3
D 4
E 1
The result should be the following
list1 = A, B (sum=7)
list2 = C, D, E (sum=8)
With this other list
key value
A 1
B 1
C 1
D 1
E 9
The result should be the following
list1 = A, B, C, D (sum=4)
list2 = E (sum=9)
Thank's in advance to those who will provide me with directions.
sf
Logic goes as:
Fetch max item and min item (min item should not be equal to max item) from original list
Add max item to list having smaller sum
Remove max and min items from original lists
last single item goes to list having lesser sum.
List<Data> list = new List<Data>()
{
new Data { Key="A",Val=9 },
new Data { Key="B",Val=1 },
new Data { Key="D",Val=1 },
new Data { Key="C",Val=1 },
new Data { Key="E",Val=1 }
};
List<Data> list1 = new List<Data>();
List<Data> list2 = new List<Data>();
while (list.Any())
{
var max = list.Max(p => p.Val);
var min = list.Min(p => p.Val);
var maxItem = list.FirstOrDefault(p => p.Val == max);
var minItem = list.FirstOrDefault(p => p.Val == min && max != min);
if (maxItem == null)
{
if (list1.Sum(p => p.Val) < list2.Sum(p => p.Val))
list1.Add(minItem);
else
list2.Add(minItem);
}
else if(minItem == null)
{
if (list1.Sum(p => p.Val) < list2.Sum(p => p.Val))
list1.Add(maxItem);
else
list2.Add(maxItem);
}
else
{
if (list1.Sum(p => p.Val) < list2.Sum(p => p.Val))
{
list1.Add(maxItem);
list2.Add(minItem);
}
else
{
list2.Add(maxItem);
list1.Add(minItem);
}
}
list.Remove(minItem);
list.Remove(maxItem);
}
var sumList1 = list1.Sum(p => p.Val);
var sumList2 = list2.Sum(p => p.Val);
You can use a for-loop:
int minDelta = int.MaxValue;
var list1 = new List<ClassName>();
var list2 = new List<ClassName>();
for (int i = 0; i < list.Count - 1; i++)
{
int count = i + 1;
int sum1 = list.Take(count).Sum(x => x.Value);
int sum2 = list.Skip(count).Sum(x => x.Value);
int delta = Math.Abs(sum1 - sum2);
if (delta < minDelta)
{
minDelta = delta;
list1 = list.Take(count).ToList();
list2 = list.Skip(count).ToList();
}
}
Using Linq and a few dictionarys (one sorted).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication85
{
class Program
{
static void Main(string[] args)
{
int index = 0;
List<string> list1 = null;
List<string> list2 = null;
Dictionary<string,int> dict1 = new Dictionary<string,int>() {
{"A", 5},
{"B", 2},
{"C", 3},
{"D", 4},
{"E", 1}
};
index = ReturnSmallestDiffIndex(dict1.AsEnumerable().Select(x => x.Value).ToList());
list1 = dict1.AsEnumerable().Take(index).Select(x => x.Key).ToList();
list2 = dict1.AsEnumerable().Skip(index).Take(dict1.Count - index).Select(x => x.Key).ToList();
Dictionary<string, int> dict2 = new Dictionary<string, int>() {
{"A", 1},
{"B", 1},
{"C", 1},
{"D", 1},
{"E", 9}
};
index = ReturnSmallestDiffIndex(dict2.AsEnumerable().Select(x => x.Value).ToList());
list1 = dict1.AsEnumerable().Take(index).Select(x => x.Key).ToList();
list2 = dict1.AsEnumerable().Skip(index).Take(dict1.Count - index).Select(x => x.Key).ToList();
}
static int ReturnSmallestDiffIndex(List<int> input)
{
SortedDictionary<int, List<int>> dict = new SortedDictionary<int, List<int>>();
for(int index = 1; index < input.Count; index++)
{
int diff = input.Skip(index).Take(input.Count - index).Sum() - input.Take(index).Sum();
if(dict.ContainsKey(Math.Abs(diff)))
{
dict[Math.Abs(diff)].Add(index);
}
else
{
dict.Add(Math.Abs(diff), new List<int>() {index});
}
}
return dict.AsEnumerable().FirstOrDefault().Value.FirstOrDefault();
}
}
}
Not efficient but Linq-heavy solution:
var values = new[] { 5, 2, 3, 4, 1 };
int[] sums = values.Select((element, index) => values.Skip(index).Sum()).ToArray();
int[] reverseSums = values.Select((element, index) => values.Take(index).Sum()).ToArray();
int[] diffs = sums.Select((element, index) => Math.Abs(element - reverseSums[index])).ToArray();
int minDiff = diffs.Min();
int[] firstPart = values.TakeWhile((element, index) => diffs[index] > minDiff).ToArray();
int[] lastPart = values.Skip(firstPart.Length).ToArray();
Dictionary<string, int> dict1 = new Dictionary<string, int>()
{
{"A", 5},
{"B", 2},
{"C", 3},
{"D", 4},
{"E", 1}
};
var result = Enumerable.Range(1, dict1.Count - 1).Select(i =>
{
var first = dict1.Take(i);
var second = dict1.Skip(i);
int diff = Math.Abs(first.Sum(x => x.Value) - second.Sum(x => x.Value));
return new {First = first, Second = second, Diff = diff};
}).OrderBy(x => x.Diff).First();
Console.WriteLine(result.Diff);
Console.WriteLine(string.Join(" ", result.First.Select(x => x.Value)));
Console.WriteLine(string.Join(" ", result.Second.Select(x => x.Value)));
I don't know if this is the fastest way, but here is what it does:
I try each possibility (i being the splitting index I iterate over)
for every splitting index i I split the dictionary and calculate the diff
I order the resulting objects by that diff
and finally take the first one
This is of course not very performance optimized, as I have to build the sums for all possibilities. One improvement could be to start in the middle instead of i = 1
I have the two lists:
List<string> keys = new List<string>()
{
"REPORTMONTH",
"CONTRACT", "DATE", "AMOUNT",
"CONTRACT", "DATE", "AMOUNT"
};
List<string> values = new List<string>()
{
"01",
"ABC123", "01022014", "300.00",
"DEF345", "03042014", "400.00"
};
The first list represents keywords which can have certain repetitions. The second list contains values associated with the keys in the first list (by index). The result output should be of type List<Dictionary<string, string>> and contain:
1st dictionary
key value
"REPORTMONTH" "01"
"CONTRACT" "ABC123"
"DATE" "01022014"
"AMOUNT" "300.00"
2nd dictionary
key value
"REPORTMONTH" "01"
"CONTRACT" "DEF345"
"DATE" "03042014"
"AMOUNT" "400.00"
I.e. the keys that do not repeat should present in both dictionaries, the rest should be splitted into dictionaries with associated values.
Note, there can be no repeptitions at all, or more than 2.
Sorry, I cannot show my attempts for this question, because I'm not sure how to start. Maybe using LINQ and grouping can solve the problem?
Thank you.
You could do this in a way that does not look that elegant, requiring some loops. Note that this will also work if there are more than 2 dictionaries.
public static void Main(params string[] args)
{
List<string> keys = new List<string>() {
"REPORTMONTH",
"CONTRACT", "DATE", "AMOUNT",
"CONTRACT", "DATE", "AMOUNT"
};
List<string> values = new List<string>() {
"01",
"ABC123", "01022014", "300.00",
"DEF345", "03042014", "400.00"
};
var pairs = keys.Select((key, ndx) => new { Key = key, Value = values[ndx] });
var groups = pairs.GroupBy(e => e.Key)
.ToDictionary(g => g.Key, g => g.Select(kvp => kvp.Value).ToArray());
var dictionaries = new Dictionary<string, string>[groups.Max(g => g.Value.Length)];
for (var i = 0; i < dictionaries.Length; i++)
{
dictionaries[i] = new Dictionary<string,string>();
foreach (var g in groups)
{
if (g.Value.Length == 1)
dictionaries[i][g.Key] = g.Value[0];
else if (g.Value.Length > i)
dictionaries[i][g.Key] = g.Value[i];
}
}
// print content
for (var i = 0; i < dictionaries.Length; i++)
{
Console.WriteLine("Dictionary {0}:", i + 1);
Console.WriteLine(string.Join(Environment.NewLine, dictionaries[i].Select(e => string.Format("{0} = {1}", e.Key, e.Value))));
Console.WriteLine();
}
Console.ReadLine();
}
You can do this by first using Enumerable.Zip() to get a sequence of key/value pairs and convert the list into a lookup, then process that list into two dictionaries:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
static void Main()
{
List<string> keys = new List<string>
{
"REPORTMONTH",
"CONTRACT", "DATE", "AMOUNT",
"CONTRACT", "DATE", "AMOUNT"
};
List<string> values = new List<string>
{
"01",
"ABC123", "01022014", "300.00",
"DEF345", "03042014", "400.00"
};
var combined = Enumerable.Zip(
keys, values, (key, value) => new { Key = key, Value = value})
.ToLookup(entry => entry.Key);
var dicts = new []
{
new Dictionary<string, string>(),
new Dictionary<string, string>()
};
foreach (var items in combined)
{
int count = 0;
string lastKey = null;
foreach (var item in items.Take(2))
{
dicts[count++][item.Key] = item.Value;
lastKey = item.Key;
}
if (count == 1)
dicts[1][lastKey] = dicts[0][lastKey];
}
dump("1st dictionary", dicts[0]);
dump("2nd dictionary", dicts[1]);
}
static void dump(string title, Dictionary<string, string> data)
{
Console.WriteLine(title);
foreach (var item in data)
Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
Console.WriteLine();
}
}
}