I have a dictionary from which I like to create a multidimensional array through c#.
foreach (KeyValuePair<string, int> pair in rptdata)
{
string s2 = pair.Key;
int s1 = pair.Value;
// var ccdata1 = new[] { new object[] { "Item1", 1 } };
// object value = cdata1[s1,s1];
}
I need to add code inside the foreach look so that it can create something like the following:
var ccdata = new[] { new object[] { "Item1", 1 }, new object[] { "Item2", 2 } };
Note that Item1,Item2 would come from str1 and 1,2 would come from int1.
I am not sure how to iterate though to populate the multidimensional object array.
You could do it in one query like this. Linq is pretty great at transforming data. If you want to turn it into JSON afterwards you can use a library, something like Json.NET.
var ccdata = rptdata
.Select( i => new object[]{ i.Key, i.Value } )
.ToArray();
Related
I have this code snippet as below which iterates over a split string.
if (!string.IsNullOrEmpty(profile.ContactNumber))
{
var splitContract = profile.ContactNumber.Split(new string[] { "and", "&" }, StringSplitOptions.RemoveEmptyEntries);
foreach (var contract in splitContract)
{
//check the split if it contains "x" or "X" character - if it does contain, it means it's a valid contract
if (contract.Contains("x") || contract.Contains("X"))
{
var condensedString = contract.Replace(" ", "");
var split = condensedString.Split(new char[] { 'x', 'X' });
GetNumbersOnly(split);
}
}
}
private void GetNumbersOnly(string[] inputArray)
{
var ListKeyValuePair = new List<KeyValuePair<string, string>>();
foreach (var item in inputArray)
{
var numberToAdd = Regex.Replace(item, "[^0-9]", "", RegexOptions.None);
ListKeyValuePair.Add(?, ?);
}
}
In GetNumbersOnly method, how can I populate List of KeyValuePair inside the for each loop?
The inputArray variable has an array element of [0] = 100, [1] = 5 for the first iteration and so on.
This is the desired output for the KeyValuePair {100, 5}, {200, 10}, {500, 15}.
Sorry, I can't seem to find any related scenario when I googled it. Any help with this is greatly appreciated.
Because the key and value are stored in separate array items, your logic is dependent on order. In cases like this, you should avoid for...each and instead use plain old for, which allows you to control the manner of iteration.
private void GetNumbersOnly(string[] inputArray)
{
var ListKeyValuePair = new List<KeyValuePair<string, string>>();
for (int i=0; i< inputArray.Length; i+=2) //The "2" here is very important!
{
var numberToAdd1 = Regex.Replace(inputArray[i], "[^0-9]", "", RegexOptions.None);
var numberToAdd2 = Regex.Replace(inputArray[i+1], "[^0-9]", "", RegexOptions.None);
ListKeyValuePair.Add(new KeyValuePair<string, string>(numberToAdd1, numberToAdd2));
}
}
The ListKeyValuePair.Add( ) function is expecting 1 field which is of type KeyValuePair. You need to make one of these with a new KeyValuePair() { key = item, value = numberToAdd };
Why are you keeping key value pairs in a list? Why not a Dictionary ? Do you want duplicate pairs?
I want to input a List<string[]> and
The output is a dictionary where the keys are unique strings used for an index and the values is an array of floats with each position in the array representing the count of the key for a string[] in the List<string[]>
So far here is what I attempted
static class CT
{
//Counts all terms in array
public static Dictionary<string, float[]> Termfreq(List<string[]> text)
{
List<string> unique = new List<string>();
foreach (string[] s in text)
{
List<string> groups = s.Distinct().ToList();
unique.AddRange(groups);
}
string[] index = unique.Distinct().ToArray();
Dictionary<string, float[]> countset = new Dictionary<string, float[]>();
return countset;
}
}
static void Main()
{
/* local variable definition */
List<string[]> doc = new List<string[]>();
string[] a = { "That", "is", "a", "cat" };
string[] b = { "That", "bat", "flew","over","the", "cat" };
doc.Add(a);
doc.Add(b);
// Console.WriteLine(doc);
Dictionary<string, float[]> ret = CT.Termfreq(doc);
foreach (KeyValuePair<string, float[]> kvp in ret)
{
Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
}
Console.ReadLine();
}
I got stuck on the dictionary part. What is the most effective way to implement this?
It sounds like you could use something like:
var dictionary = doc
.SelectMany(array => array)
.Distinct()
.ToDictionary(word => word,
word => doc.Select(array => array.Count(x => x == word))
.ToArray());
In other words, first find the distinct set of words, then for each word, create a mapping.
To create a mapping, look at each array in the original document, and find the count of the occurrences of the word in that array. (So each array maps to an int.) Use LINQ to perform that mapping over the whole document, with ToArray creating an int[] for a particular word... and that's the value for that word's dictionary entry.
Note that this creates a Dictionary<string, int[]> rather than a Dictionary<string, float[]> - it seems more sensible to me, but you could always cast the result of Count to float if you really wanted to.
Assuming the 2 string arrays are the same length and not empty how can I make a List of the contents?
I had a Dictionary working, but now I need to be able to use duplicate keys so I am resorting to a List.
string[] files = svd.file.Split(",".ToCharArray());
string[] references = svd.references.Split(",".ToCharArray());
Dictionary<string, string> frDictionary = new Dictionary<string, string>();
frDictionary = files.Zip(rReferences, (s, i) => new { s, i })
.ToDictionary(item => item.s, item => item.i);
I could do it like:
List<string, string> jcList = new List<string, string>();
and then just have a double loop into the two arrays but I know a faster way must exist.
ILookup<string,string> myLookup =
files.Zip(rReferences, (s, i) => new { s, i })
.ToLookup(item => item.s, item => item.i);
will create a Dictionary-like structure that allows multiple values per key.
So
IEnumerable<string> foo = myLookup["somestring"];
A List containing elements with two strings each is simplest implemented with a
List<T>
and
T == Tuple<string,string>
Then use a loop to build your list from the two arrays:
string[] s1 =
{
"1", "2"
};
string[] s2 =
{
"a", "b"
};
var jcList = new List<Tuple<string,string>>();
for (int i = 0; i < s1.Length; i++)
{
jcList.Add(Tuple.Create(s1[i], s2[i]));
}
or using LINQ:
var jcList = s1.Select((t, i) => Tuple.Create(t, s2[i])).ToList();
Working with an API where I need to send a value over in an array of NVPairs, like the following:
new[]
{
new[]
{
new NVPair
{
name = "email_address",
value = "email1#email.com"
}
},
new[]
{
new NVPair
{
name = "email_address",
value = "email2#email.com"
}
}
}
I need to be able to create this (the value, or "email2#email.com") from a list of strings (that will be the email addresses).
Would anyone be able to provide some guidance?
Assuming you really want an array of single-element arrays, I suspect you want:
var nvPairs = strings.Select(x => new[] { new NVPair("email_address", x) })
.ToArray();
This is also assuming that the NVPair type in question has a two-parameter constructor, taking the name and the value. If it doesn't, the query becomes uglier:
var nvPairs = strings.Select(x => new[] { new NVPair { name = "email_address",
value = x } })
.ToArray();
Note the new[] so that each element is transformed into a single-element array.
Another option which would at least work from a compile-time point of view is to create a single-element outer array, where its sole element was a multi-element array:
var nvPairs = new[] { strings.Select(x => new NVPair("email_address", x))
.ToArray() };
Assuming you want to create an array of NVPairs, rather than an array of single-element NVPair arrays, you can use Linq to achieve this:
using System.Linq;
...
var strings = new[] { "email1#email.com", "email2#email.com" };
var nvpairArray = strings.Select(s => new NVPair { name = "email_address", value = s }).ToArray();
Update
NVPair[][] nvpairArrayOfArrays = strings.Select(s => new NVPair[] { new NVPair { name = "email_address", value = s } }).ToArray();
I have a list like
List<string> TempList = new List<string> { "[66,X,X]", "[67,X,2]", "[x,x,x]" };
I need to add data to the dictionary from the above list
Dictionary<int, int> Dict = new Dictionary<int, int>();
so the Dict should contain
Key --> 66 value --> 67
i need to take 66(first value) from first string([66,X,X]) and 67(first value) from second string( [67,X,X]) and add it as a key value pair into the dictionary.
Now i'm following string replacing and looping methodology to do this .
Is there any way to do this in LINQ or Regular expression.
After your comment that you're starting from a list of lists, I understood what you were after. I'm reusing Jaroslav's 'GetNumber' function here. Wrote my sample with array of array of string, but should work just the same. The code below will throw if you have duplicate keys, which I presume is what you want if you're using a dictionary.
var input = new []
{
new [] { "[66,X,X]", "[67,X,2]", "[x,x,x]" },
new [] { "[5,X,X]", "[8,X,2]", "[x,x,x]" }
};
var query = from l in input
select new
{
Key = GetNumber(l.ElementAt(0)),
Value = GetNumber(l.ElementAt(1))
};
var dictionary = query.ToDictionary(x => x.Key, x => x.Value);
Here is an example using both string.Split() and a Regex:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<string> data = new List<string>() { "[66,X,X]", "[67,X,2]", "[x,x,x]" };
addToDict(data);
Console.ReadKey();
}
private static void addToDict(List<string> items)
{
string key = items[0].Split('[', ',')[1];
string val = items[1].Split('[', ',')[1];
string pattern = #"(?:^\[)(\d+)";
Match m = Regex.Match(items[0], pattern);
key = m.Groups[1].Value;
m = Regex.Match(items[1], pattern);
val = m.Groups[1].Value;
_dict.Add(key, val);
}
static Dictionary<string, string> _dict = new Dictionary<string, string>();
}
}
i suspect that your example is quite contrived though, so there may be a better solution especially if you need to process large numbers of strings into key/value pairs (i deliberately hardcoded index values because your example was quite simple and i didn't want to over complicate the answer). If the input data is consistent in format then you can make assumptions like using fixed indexes, but if there is a possibility of some variance then there may need to be more code to check the validity of it.
You can use a regular expression to extract the value from each item in the list, and if you want, use LINQ to select out two lists and zip them together (in C# 4.0):
var regex = new Regex(#"\d+");
var allValues = TempList.Select(x =>int.Parse(regex.Match(x).Value));
var dictKeys = allValues.Where((x,index)=> index % 2 == 0); //even-numbered
var dictValues = allValues.Where((x,index)=> index % 2 > 0); //odd numbered
var dict = dictKeys.Zip(dictValues, (key,value) => new{key,value})
.ToDictionary(x=>x.key,x=>x.value);
If you're using C# 3.5, you can use Eric Lippert's implementation of Zip().
IF I understand correctly: you want to create linked nodes like 66 -> 67, 67 -> 68, ... n -> n+1?
I would not use LINQ:
private static int GetNumber(string s)
{
int endPos = s.IndexOf(',');
return Int32.Parse(s.Substring(1, endPos-1));
}
And in code:
int first, second;
for (int i = 1; i < TempList.Count; i++)
{
first = GetNumber(TempList[i - 1]);
second = GetNumber(TempList[i]);
Dict.Add(first, second);
}
You should also perform checking, etc.
The sample assumes a list with at least 2 items.
List<List<string>> source = GetSource();
Dictionary<int, int> result = source.ToDictionary(
tempList => GetNumber(tempList[0]),
tempList => GetNumber(tempList[1])
);