c# reversing and serializing a dictionary using linq - c#

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)));

Related

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();

How to deal with parallel arrays in LINQ?

I have 2 separate arrays (coming from Json, but that's not important). They are lined up... i.e. arr1[1] goes with arr2[1].
I want to create a list of Test objects with a few catches:
1) both arr1 and arr2 value can't be null
2) I'm only interested in indexes where the arr1 element is a multiple of 5
This is what I have so far:
class Test
{
public double d1;
public double d2;
}
class Program
{
static void Main(string[] args)
{
string[] arr1 = new string[] { "0", "2", "5", "7", "10", "11", null, "13", "15" };
string[] arr2 = new string[] { "11", "13", "56", "8", null, "44", "55", "66", "77" };
var v = arr1.Where(x => !String.IsNullOrEmpty(x)).Select(x => Double.Parse(x)).Where(x => (x % 5) == 0).Select((x, y) => new Test
{
d1 = x,
d2 = Double.Parse(arr2[y])
});
}
}
I'm not sure how to skip the ones where arr2 is null though and the alignment is getting messed up.
In order not to mess up alignment, you should first .Zip the two arrays. Then, if I understand correctly, those indices that have null as value in either array should be skipped, so you filter those out with .Where, then do the rest of your logic.
class Test
{
public double d1;
public double d2;
}
class Program
{
static void Main(string[] args)
{
string[] arr1 = new string[] { "0", "2", "5", "7", "10", "11", null, "13", "15" };
string[] arr2 = new string[] { "11", "13", "56", "8", null, "44", "55", "66", "77" };
var v = arr1
.Zip(arr2, (x, y) => new {x, y})
.Where(a => !string.IsNullOrEmpty(a.x) && !string.IsNullOrEmpty(a.y))
.Select(a => new Test { d1 = double.Parse(a.x), d2 = double.Parse(a.y) })
.Where(a => (a.d1 % 5) == 0);
// TODO, ready to enumerate over v.
}
}
You can filter by where condition as below.
class Program
{
static void Main(string[] args)
{
string[] arr1 = new string[] { "0", "2", "5", "7", "10", "11", null, "13", "15" };
string[] arr2 = new string[] { "11", "13", "56", "8", null, "44", "55", "66", "77" };
var v = arr1
.Zip(arr2, (x, y) => new { x, y })
.Where(a => !string.IsNullOrEmpty(a.x) && !string.IsNullOrEmpty(a.y))
.Select(a => new Test { d1 = double.Parse(a.x), d2 = double.Parse(a.y) })
.Where(a => (a.d1 % 5) == 0);
}
}

Construct a new Dictionary based on value criteria

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

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);

Categories

Resources