I have 2 different collections.
pseudo code:
// index string by int : Dictionary<int, string>
index = { 0, "a" }, { 1, "b" }, { 2, "c" }
// data : Dictionary<string, List<Data>>
data = {"a", { "data00", "data01"..}},
{"b", {"data20", "data21", "data22"...}},
{"c", {"data4",...}}...
I want project int index to data string value and
var result = data.SelectMany ... new { IntIndex, DataValue }
I need to flatten lists into one sequence and pair the Data values with int index using string index.
I have slightly update types and values (your Dictionary contains duplicated keys and index wasn't specified) but it shouldn't be a problem. You may modify function easily for your data types.
var index = new List<Tuple<int, string>> {Tuple.Create(0, "a"), Tuple.Create(1, "b")};
var data = new Dictionary<string, IEnumerable<string>>()
{
{"a", new[] {"data00", "data01"}},
{"b", new[] {"data20", "data21", "data22"}},
{"c", new[] {"data4"}}
};
var result = index
.Join(data, x => x.Item2, y => y.Key, (x,y) => new KeyValuePair<int, IEnumerable<string>>(x.Item1, y.Value))
.SelectMany(x => x.Value, (x, y) => new KeyValuePair<int, string>(x.Key, y));
Assuming your duplication of keys was accidental, you could try this
Dictionary<int, List<Data>> intData = new Dictionary<int, List<Data>>();
foreach (var iVal in index)
{
List<Data> tmpList = new List<Data>();
if (data.TryGetValue(iVal.Value, out tmpList))
{
intData.Add(iVal.Key, tmpList);
}
}
If you can have duplicate keys then a dictionary is not the right structure.
var index = new List<Tuple<int, string>> {Tuple.Create(0, "a"), Tuple.Create(1, "b")};
var data = new Dictionary<string, IEnumerable<string>>()
{
{"a", new[] {"data00", "data01"}},
{"b", new[] {"data20", "data21", "data22"}},
{"c", new[] {"data4"}}
};
var res =
(from i in index
join d in data on i.Item2 equals d.Key
select new {Key = i.Item1, Value = d.Value})
.SelectMany(x => x.Value, (x, v) => new {x.Key, Value = v});
Related
I am trying to write a method which should return the item value based on value index and condition.
For example, in the below, if I pass index value as 0, it should return keys and first value from integer array which is not having value 5.
public static Dictionary<string, int[]> _dict = new Dictionary<string, int[]>()
{
{"A", [1,0,3] },
{"B", [5,1,5] },
{"C", [7,11,5] },
{"D", [0,1,5]},
{"E", [14,0,5] },
{"F", [5,1,5] }
};
Expected O/P:
if I pass index value 0, and condition as != 5 then O/P should be
{
{"A", 1 },
{"C", 7 },
{"D", 0 },
{"E", 14}
};
You could achieve this in two steps:
Get those items that do not start with 5
var res = _dict.Where(a => a.Value[0] !=5);
Then populate a new Dictionary with the remaining keys and the first entry in their integer array
foreach(KeyValuePair<string,int[]> keyValuePair in res)
{
result.Add(keyValuePair.Key, keyValuePair.Value[0]);
}
or using LINQ
result = res.ToDictionary(keyValue => keyValue.Key, keyValue => keyValue.Value[valueIndex]);
Complete code would look something like
public static Dictionary<string, int[]> _dict = new Dictionary<string, int[]>()
{
{"A", new int[] {1,0,3 } },
{"B", new int[] {5,1,5} },
{"C", new int[] {7,11,5} },
{"D", new int[] {0,1,5}},
{"E", new int[] {14,0,5} },
{"F", new int[] {5,1,5} }
};
static Dictionary<string, int> GetResult(int valueIndex, Func<KeyValuePair<string, int[]>, bool> predicate) =>
_dict.Where(predicate)
.ToDictionary(keyValue => keyValue.Key, keyValue => keyValue.Value[valueIndex]);
GetResult(valueIndex: 0, predicate: a => a.Value[0] != 5) then gives the result you want
{
{"A", 1 },
{"C", 7 },
{"D", 0 },
{"E", 14}
};
One line code using LINQ
var result = _dict.Where(x => x.Value[0] != 5).ToDictionary(x => x.Key, y => y.Value[0]);
I would like to create a
Dictionary<string, int[]> dict
out of two arrays:
string[] keys = { "A", "B", "A", "D" };
int[] values = { 1, 2, 5, 2 };
the result:
["A"] = {1,5}
["B"] = {2}
["D"] = {2}
Is there a way i can do this with LINQ?
I have read about Zip but I don't think I can use since I need to add values to an existing key.value array.
Use .Zip to bind the two collections together and then GroupBy to group the keys.
string[] keys = { "A", "B", "A", "D" };
int[] values = { 1, 2, 5, 2 };
var result = keys.Zip(values, (k, v) => new { k, v })
.GroupBy(item => item.k, selection => selection.v)
.ToDictionary(key => key.Key, value => value.ToArray());
Then to add these items into the dictionary that you already have:
I changed the int[] to List<int> so it is easier to handle Add/AddRange
Dictionary<string, List<int>> existingDictionary = new Dictionary<string, List<int>>();
foreach (var item in result)
{
if (existingDictionary.ContainsKey(item.Key))
existingDictionary[item.Key].AddRange(item.Value);
else
existingDictionary.Add(item.Key, item.Value.ToList());
}
Linq solution:
string[] keys = { "A", "B", "A", "D" };
int[] values = { 1, 2, 5, 2 };
Dictionary<string, int[]> dict = keys
.Zip(values, (k, v) => new {
key = k,
value = v })
.GroupBy(pair => pair.key, pair => pair.value)
.ToDictionary(chunk => chunk.Key,
chunk => chunk.ToArray());
Test:
string report = String.Join(Environment.NewLine, dict
.Select(pair => $"{pair.Key} [{string.Join(", ", pair.Value)}]"));
Console.Write(report);
Outcome:
A [1, 5]
B [2]
D [2]
Try this :
string[] keys = { "A", "B", "A", "D" };
int[] values = { 1, 2, 5, 2 };
Dictionary<string, int[]> dict = keys.Select((x, i) => new { key = x, value = values[i] }).GroupBy(x => x.key, y => y.value).ToDictionary(x => x.Key, y => y.ToArray());
I have
List<string> strs;
double[] values;
where the values array contains the value of each of the string in strs list
Say strs={"abc","def","ghi"}
and values={3,1,2}
this means "abc" has value 3 and so on.
I wish to sort strs and values ordered by values, such that it becomes
strs={"def","ghi","abc"}
values={3,2,1}
I am using
string[] strsArr = strs.ToArray();
Array.Sort(values, strsArr);//1. sort it ascendingly
strs = strsArr.ToList();
Array.Reverse(strs);//2. reverse it
Is there a way I can sort it in descending sequence directly without 2 phases?
You can use a Dictionary and Linq to solve this.
var dict = new Dictionary<string, double>()
{
{"abc",3},
{"def",1},
{"ghi",2}
};
var sorted = dict.OrderByDescending(g => g.Value)
.Select(g => g.Key)
.ToArray();
Note, unless you have a ToArray() at the end the sorting will be deferred till later enumerated and may accidentally be enumerated multiple times.
How about this:
var strs = new [] { "abc", "def", "ghi", };
var values = new [] { 3, 1, 2, };
strs =
strs
.Zip(values, (s, v) => new { s, v })
.OrderByDescending(sv => sv.v)
.Select(sv => sv.s)
.ToArray();
try use dictionary:
Dictionary<string, double> dictionary = new Dictionary<string, double>();
dictionary.Add("abc", 3);
dictionary.Add("def", 1);
dictionary.Add("ghi", 2);
var sortedDict = dictionary.OrderByDescending(x => x.Value);
double[] values = sortedDict.Select(x => x.Value).ToArray();
List<string> strs = sortedDict.Select(x => x.Key).ToList();
I have a dict<string, list<string>>, say 3 keys in dict, the first key has 2 values, the secodn 3 values, the third key has 3 values. If I get a value from each value set, then I will have a combination of 2*3*3 = 18 sets
How to code in c#?
thanks
Edit
Sorry did not make it clear
I want something like this
say I have dict like this
{"1",new List<String>(){"a", "b"}},
{"2",new List<String>(){"c", "d", "e"}},
{"3", new List<string>() {"f", "g"}
I want output like this
acf, acg, adf, adg, aef, aeg
bcf, bcg, bdf, bdg, bef, beg
With Linq:
var dict = new Dictionary<String, List<String>>() {
{"1",new List<String>(){"a", "b"}},
{"2",new List<String>(){"c", "d", "e"}},
{"3",new List<String>(){"f", "g", "h"}},
};
var combis = from kv in dict
from val1 in kv.Value
from val2 in kv.Value
select string.Format("{0}{1}", val1, val2);
foreach (var combi in combis)
Console.WriteLine(combi);
demo: http://ideone.com/nm7mY
Quick & dirty but you may polish this method. The result list contains expected result:
Usage:
var dict = new Dictionary<String, List<String>>() {
{"1",new List<String>(){"a", "b"}},
{"2",new List<String>(){"c", "d", "e"}},
{"3",new List<String>(){"f", "g"}},
};
var collections = dict.Select(kvp => kvp.Value).ToArray();
var result = new List<string>();
GetNextProduct(collections, 0, String.Empty, result);
Method that produces the result:
private static void GetNextProduct(IEnumerable<string>[] collections, int collectionIndex, string currentProduct, IList<string> results)
{
var currentList = collections[collectionIndex];
bool isLast = collections.Length == collectionIndex + 1;
foreach (var s in currentList)
{
if (isLast) results.Add(currentProduct + s);
else GetNextProduct(collections, collectionIndex + 1, currentProduct + s, results);
}
}
I think you mean this?
Dictionary<string, int> dict = new Dictionary<string, int>
{
{ "Hello World", 1 },
{ "HelloWorld", 1 },
{ "Hello World", 1 },
};
foreach (var item in dict) // var is of type KeyValuePair<string, int>
Console.WriteLine(item.Key + ", " + item.Value);
Dictionary<string, List<int>> storage = new Dictionary<string, List<int>>();
storage.Add("key1", new List<int>() { 2, 7 });
storage.Add("key2", new List<int>() { 8, 4, 1});
storage.Add("key3", new List<int>() { 3, 9, 3 });
foreach (string key in storage.Keys)
{
//access to single storage...
List<int> subStorage = (List<int>)storage[key];
foreach (int item in subStorage)
{
//access to single value inside storage...
}
}
I would try something like the following if I was trying to read or edit the values in the lists:
Dictionary<int, List<string>> dict = new Dictionary<int, List<string>>();
var arrayOfValues = dict.Values.ToArray();
for (int i = 0; i < arrayOfValues.Length; i++)
{
for (int j = 0; j < arrayOfValues[i].Count; j++)
{
//read/edit arrayOfValues[i][j];
}
}
You do not need recursion since you know the dept of the "tree".
I am trying to create a dictionary from 2 lists where one list contains keys and one list contains values. I can do it using for loop but I am trying to find if there is a way of doing it using LINQ.
Sample code will be helpfull. Thanks!!!!
In .NET4 you could use the built-in Zip method to merge the two sequences, followed by a ToDictionary call:
var keys = new List<int> { 1, 2, 3 };
var values = new List<string> { "one", "two", "three" };
var dictionary = keys.Zip(values, (k, v) => new { Key = k, Value = v })
.ToDictionary(x => x.Key, x => x.Value);
List<string> keys = new List<string>();
List<string> values = new List<string>();
Dictionary<string, string> dict = keys.ToDictionary(x => x, x => values[keys.IndexOf(x)]);
This of course assumes that the length of each list is the same and that the keys are unique.
UPDATE: This answer is far more efficient and should be used for lists of non-trivial size.
You can include the index in a Select expression to make this efficient:
var a = new List<string>() { "A", "B", "C" };
var b = new List<string>() { "1", "2", "3" };
var c = a.Select((x, i) => new {key = x, value = b[i]}).ToDictionary(e => e.key, e => e.value );
foreach (var d in c)
Console.WriteLine(d.Key + " = " + d.Value);
Console.ReadKey();
var dic = keys.Zip(values, (k, v) => new { k, v })
.ToDictionary(x => x.k, x => x.v);
You can use this code and working perfectly.
C# Code:
var keys = new List<string> { "Kalu", "Kishan", "Gourav" };
var values = new List<string> { "Singh", "Paneri", "Jain" };
Dictionary<string, string> dictionary = new Dictionary<string, string>();
for (int i = 0; i < keys.Count; i++)
{
dictionary.Add(keys[i].ToString(), values[i].ToString());
}
foreach (var data in dictionary)
{
Console.WriteLine("{0} {1}", data.Key, data.Value);
}
Console.ReadLine();
Output Screen: