Construct a new Dictionary based on value criteria - c#

I want to build a dictionary from
Dictionary<int, List<string>> dict = new Dictionary<int, List<string>>();
dict.Add(1, new List<string>() { "1", "2", "3" });
dict.Add(2, new List<string>() { "4", "5", "6" });
dict.Add(3, new List<string>() { "7", "8", "9" });
such that the criteria is the count of Values of List satisfies given integer i.
Ex:
for i=4
I want the result to be
Dictionary<int, List<string>> res= new Dictionary<int, List<string>>();
dict.Add(1, new List<string>() { "1", "2", "3" });
dict.Add(2, new List<string>() { "4"});
and for i=7
I want the result to be
Dictionary<int, List<string>> res= new Dictionary<int, List<string>>();
dict.Add(1, new List<string>() { "1", "2", "3" });
dict.Add(2, new List<string>() { "4", "5", "6" });
dict.Add(3, new List<string>() { "7"});
I tried using Take while for i=5 but it is not worthy.
var res = dict.Select(x => x).TakeWhile(y => dict.Values.ToList().Count < 6);
Any suggestions please?

You can iterate through the original dictionary and calculate the count of values on each iteration and then populate the result dictionary like:
int i = 4;
Dictionary<int, List<string>> res = new Dictionary<int, List<string>>();
foreach (var item in dict)
{
int takeItems = i - res.Values.SelectMany(r => r).Count();
if (takeItems > 0)
{
res.Add(item.Key, item.Value.Take(takeItems).ToList());
}
else
{
break;
}
}
DEMO

Related

How to convert a dictionary of lists into a list of unique dictionaries according to a particular combinatorial logic?

I have a dictionary of lists like so:
var dictOfLists = new Dictionary<string, List<string>>
{
["foo"] = new List<string>{ "a", "b", "c" },
["bar"] = new List<string>{ "d" },
["baz"] = new List<string>{ "e", "a" }
}
I want to convert this to a list of unique dictionaries like so:
var listOfUniqDicts = new List<Dictionary<string, string>>
{
new Dictionary<string, string> {["foo"] = "a", ["bar"] = "d", ["baz"] = "e" },
new Dictionary<string, string> {["foo"] = "a", ["bar"] = "d", ["baz"] = "a" },
new Dictionary<string, string> {["foo"] = "b", ["bar"] = "d", ["baz"] = "e" },
new Dictionary<string, string> {["foo"] = "b", ["bar"] = "d", ["baz"] = "a" },
new Dictionary<string, string> {["foo"] = "c", ["bar"] = "d", ["baz"] = "e" },
new Dictionary<string, string> {["foo"] = "c", ["bar"] = "d", ["baz"] = "a" },
}
(As you can see, in the above list, each of the dictionaries represents a unique combination of values, whose keys map to the respective keys of the initial dictionary.)
Is there a clean algorithm to do this with an arbitrary dictionary of the above type?
It's like constructing a thruth table:
In the first column you write true, false, true, false, ...
In the second column you repeat each item 2 times: true, true false, false, true, true, false, false, ...
In the nth column you repeat each item 2^(n-1) times
This problem is a generalized version (try in dotnetfiddle):
private Dictionary<TKey, TValue>[] BuildDictionary<TKey, TValue>(Dictionary<TKey, List<TValue>> dict) where TKey : notnull
{
// Calculating the size of the result (product of the length of each entry)
int[] lengths = dict.Select(d => d.Value.Count()).ToArray();
int size = lengths.Aggregate(1, (prev, val) => prev * val); // reduce in JavaScript
var result = new Dictionary<TKey, TValue>[size];
for (int i = 0; i < result.Length; i++) { result[i] = new Dictionary<TKey, TValue>(); }
int repeats = 1;
foreach (var d in dict)
{
var key = d.Key;
for (int row = 0; row < size;)
for (int i = 0; i < repeats; i++)
foreach (var val in d.Value)
{
result[row].Add(key, val);
row++;
}
repeats *= d.Value.Count;
}
return result;
}
Result:
[
{"foo":"a","bar":"d","baz":"e"},
{"foo":"b","bar":"d","baz":"a"},
{"foo":"c","bar":"d","baz":"e"},
{"foo":"a","bar":"d","baz":"a"},
{"foo":"b","bar":"d","baz":"e"},
{"foo":"c","bar":"d","baz":"a"}
]

Can i get unmatched values from two texbox like this way?

I can get values which are already matched. But i can't get unmatched values. How to make it work. Give me some advice guys
private void button13_Click(object sender, EventArgs e)
{
String a = textBox3.Text;
String b = textBox4.Text;
string test = "";
string[] titles1 = a.Split(new[] { ';', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
string[] titles2 = b.Split(new[] { ';', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
var duplicates = titles1.Distinct().Concat(titles2.Distinct()).GroupBy(title => title).Where(possibleDuplicates => possibleDuplicates.Skip(1).Any()).Select(duplicate => duplicate.First());
int i = 0;
foreach (string duplicate in duplicates)
{
//test = test + duplicate + "\r\n";
System.Data.DataTable table = new System.Data.DataTable();
table.Columns.Add("Missed call");
table.Rows.Add(duplicate);
Excel_read.DataSource = table;
}
}
This may help for you
var result = titles1.Except(titles2).Concat(titles2.Except(titles1)).ToArray();
To find the differences you may use the following code (it is written on the fly, I don't say it is an performance-optimized algorithm, it is just an idea how your problem may be solved):
var list1 = new List<int> {1, 2, 3, 5};
var list2 = new List<int> {1, 2, 4, 5, 6};
var differences = list1.Where(v => !list2.Contains(v)).Concat(
list2.Where(v => !list1.Contains(v)));
// Or this compact version:
// var differences = list1.Except(list2).Concat(list2.Except(list1));
The differences IEnumerable will will contain the following result:
{3, 4, 6}
This way:
List<string> list1 = new List<string> { "1", "2", "3", "4", "5", "7", "9"};
List<string> list2 = new List<string> { "1", "2", "3", "4", "5", "6", "8" };
List<string> list3 = list1;
list3.AddRange(list2);
list3 = list3.GroupBy(x => x).Where(x => x.Count() == 1).Select(x => x.Key).ToList();

Compare two List<string> using LINQ in C#

What is the best way to compare two lists based on values, order and the number of values. So all of the lists below should be different.
var list1 = new List<string> { "1", "2" };
var list2 = new List<string> { "2", "1" };
var list3 = new List<string> { "1", "2", "3" };
How about using SequenceEqual.
See http://ideone.com/yZeYRh
var a = new [] { "1", "2", "3" };
var b = new [] { "1", "2" };
var c = new [] { "2", "1" };
Console.WriteLine(a.SequenceEqual(b)); // false
Console.WriteLine(a.SequenceEqual(c)); // false
Console.WriteLine(c.SequenceEqual(b)); // false
It comes from the namespace System.Linq and can be used on any IEnumerable.
You can also pass it an IEqualityComparer to for example also do:
var d = new [] { "a", "B" };
var e = new [] { "A", "b" };
Console.WriteLine(d.SequenceEqual(e, StringComparer.OrdinalIgnoreCase)); // true
I like Zip for this, but you still need to manually compare Count.
lista.Count() ==listb.Count() && lista.Zip(listb, Equals).All(a=>a);

How to sort in ascending order a dictionary Dictionary<string, List<string>> based on the value length?

Here key is a string and value is a list of string. The longest list should come first and shortest at last.
Dictionary<string, List<string>> InputDictionary = {‘A’:[A1, A2, A3, A4], ‘B’:[B1, B2], ‘C’:[C1, C2, C3]}
Output has to be
output = {‘A’:[A1, A2, A3, A4], ‘C’:[C1, C2, C3], ‘B’:[B1, B2]} based on value length.
Please reply.
This should do it for you.
Dictionary<char, List<string>> input = new Dictionary<char, List<string>>();
input.Add('A', new List<string>() { "A1", "A2", "A3", "A4" });
input.Add('B', new List<string>() { "B1", "B2", "B3", "B4", "B5" });
input.Add('C', new List<string>() { "C1", "C2", "C3" });
input.Add('D', new List<string>() { "D1", "D2" });
input = input.OrderByDescending(x => x.Value.Count).ToDictionary(x => x.Key, x => x.Value);

c# reversing and serializing a dictionary using linq

Was wondering is it possible to reverse a dictionary in a single LINQ statement?
The structure is as follows;
Dictionary<string, List<string>> original = new Dictionary<string, List<string>>()
{
{"s", new List<string>() { "1", "2", "3" }},
{"m", new List<string>() { "4", "5", "6" }},
{"l", new List<string>() { "7", "8", "9" }},
{"xl", new List<string>() { "10", "11", "12" }},
};
which i would like to convert to a dictionary of type;
Dictionary<string, string> Reverse = new Dictionary<string, string>()
{
{"1", "s"},
{"2", "s"}, //and so on
};
If you do:
var reversed = original.SelectMany(x => x.Value.Select(y => new KeyValuePair<string, string>(y, x.Key)));
then you get:
1 - s
2 - s
3 - s
4 - m
5 - m
etc.
Something like:
var result = (from kvp in original
from value in kvp.Value
select new {Key = value, Value = kvp.Key}).ToDictionary(a => a.Key, a => a.Value);
Or, if you prefer the method syntax:
var result = original.SelectMany(kvp => kvp.Value.Select(v => new {Key = v, Value = kvp.Key}))
.ToDictionary(a => a.Key, a => a.Value);
you can use a SelectMany to split the value sublists, and then reverse the Keys & Values into a new Dictionary using ToDictionary
var result = original
.SelectMany(k=> k.Value.Select(v => new { Key = v, Value = k.Key } ))
.ToDictionary( t=> t.Key, t=> t.Value);
For that you can use the SelectMany LINQ extension method:
var original = new Dictionary<string, List<string>>
{
{ "s", new List<string> { "1", "2", "3" } },
{ "m", new List<string> { "4", "5", "6" } },
{ "l", new List<string> { "7", "8", "9" } },
{ "xl", new List<string> { "10", "11", "12" } },
};
var keyValuePairs = original.SelectMany(o => o.Value.Select(v => new KeyValuePair<string, string>(v, o.Key)));

Categories

Resources