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();
Related
I'm working on one problem. I have a list<string> of detected data types ("int", "double", "string", "bool", "datetime", "timespan", "datetimeoffset").
Now I need to choose something like "default" one data type that will be used for all values in array. How to create (theoretically) the logic to setting the appropriate data type?
For example if was detected at least one string, default data type will be defined as string, because this type can "store" also other data types, such as bool or date.
Name
If i understand what you want correctly, you can make a method like this :
public static List<object> GetMostLikelyType(List<string> inputs)
{
List<object> result = new List<object>() ;
int num;
double d;
DateTime dt;
bool b;
TimeSpan ts;
DateTimeOffset dto;
if (inputs.All(i => int.TryParse(i, out num)))
result = inputs.Select(x => (object)int.Parse(x)).ToList();
else if (inputs.All(i => double.TryParse(i, out d)))
result = inputs.Select(x => (object)double.Parse(x)).ToList();
else if (inputs.All(i => DateTime.TryParse(i, out dt)))
result = inputs.Select(x => (object)DateTime.Parse(x)).ToList();
else if (inputs.All(i => bool.TryParse(i, out b)))
result = inputs.Select(x => (object)bool.Parse(x)).ToList();
else if (inputs.All(i => TimeSpan.TryParse(i, out ts)))
result = inputs.Select(x => (object)TimeSpan.Parse(x)).ToList();
else if (inputs.All(i => DateTimeOffset.TryParse(i, out dto)))
result = inputs.Select(x => (object)DateTimeOffset.Parse(x)).ToList();
else
result = inputs.Select(x => (object)x.ToString()).ToList();
return result;
}
And then use it for your List (respective outputs is commented) :
List<string> strings = new List<string>() {"2016/7/3","2025/12/01" };
//List of DateTime objects
List<string> strings2 = new List<string>() { "25", "21.12" };
//List of Double objects
List<string> strings3 = new List<string>() { "true", "false" };
//List of bool objects
List<string> strings4 = new List<string>() { "12", "0" };
//List of int objects
List<string> strings5 = new List<string>() { (new TimeSpan(2,3,3)).ToString(), "0" };
//List of TimeSpan objects
List<string> strings6 = new List<string>() { "2016/7/3" , "3"};
//string
var result = GetMostLikelyType(strings);
var result2 = GetMostLikelyType(strings2);
var result3 = GetMostLikelyType(strings3);
var result4 = GetMostLikelyType(strings4);
var result5 = GetMostLikelyType(strings5);
var result6 = GetMostLikelyType(strings6);
You could declare everything as an object since object is the base type for everything.
then you iterate through the list and test with typeof.
list<object> tt
in your loop use :
if (tt[I].GetType() == typeof(Integer))
I prefer use a list of Object or list of dynamic:
List<object> stuff = new List<object>();
stuff.add("test");
stuff.add(35);
Console.WriteLine((string)stuff[0]);
Console.WriteLine((int)stuff[1]);
and here is dynamic example:
var list = new List<dynamic>();
list.Add(123);
list.Add(new
{
Name = "Lorem Ipsum"
});
I have
List<X> A = new List<X>{null,"1",null,"3"};
List<Y> B = new List<Y>{ 0 , 1 , 2 , 3 };
I want to use linq to list only the elemnts in B that have a corresponding value in A that is not null. so...
List<Y> C = [some linq expression using A and B];
C now has 1 and 3 in it.
How can this be done?
List<String> A = new List<String> { null, "1", null, "3" };
List<int> B = new List<int> { 0, 1, 2, 3 };
var C = A.Zip(B, (s, n) => new { a = s, b = n })
.Where(x => x.a != null)
.Select(x => x.b)
.ToList();
var c = B.Where((o, i) => A[i] != null).ToList();
Edit to note that it was unclear to me when this was written that both lists are aligned by index. Unsure of the value of this response given that information. It's certainly less valuable than I initially imagined.
Essentially what you want is an intersection. Here's an answer using Intersect() that works based on the data and parameters supplied in your example:
var a = new List<string> { null, "1", null, "3" };
var b = new List<int> { 0, 1, 2, 3 };
var intersection = a.Intersect(b.Select(x => x.ToString())).ToList();
You should be able to adapt to an intersection that works for you.
If both of your lists really have nullable items in them, then you'll need additional null checks on the b list (I'm just blindly calling ToString() on each item in it). But there's no reason to filter out nulls in A if B contains no nulls and you are doing an intersection, they will be filtered out as part of that process.
Consider also that:
b.Select(x => x.ToString()) ...
Could very easily be:
b.Select(x => ConvertTypeBToTypeA(x)) ...
List<string> A = new List<string> { null, "1", null, "3" };
List<int> B = new List<int> { 0, 1, 2, 3 };
var C = B.Where(x => A.Contains(x.ToString()));
How about an extension method to avoid some overhead?
public static class Ext {
public static IEnumerable<T1> WhereOther<T1, T2>(this IEnumerable<T1> src, IEnumerable<T2> filter, Func<T2, bool> pred) {
using (var isrc = src.GetEnumerator())
using (var ifilter = filter.GetEnumerator())
while (ifilter.MoveNext())
if (isrc.MoveNext())
if (pred(ifilter.Current))
yield return isrc.Current;
}
}
With that created, you can use
var ans = B.WhereOther(A, p => p != null);
You may also want an IQueryable variant, though creating one isn't that easy.
I guess you could cheat and return a lambda that applies AsEnumerable() and then uses IEnumerable.WhereOther.
try this:
var c = Enumerable.Range(0, Math.Min(B.Count, A.Count))
.Where(i => A[i] != null)
.Select(i => B[i]).ToList();
I am trying to loop through two concurrent dictionaries like the code below, however I want to use a lambda expression instead
foreach (var s in sb_eventdata)
{
foreach (var f in final_data)
{
if (s.Value.Car.Equals(f.Value.Car))
{
Console.Writeline("Found!");
}
}
}
var values = sb_eventdata.Where(k => k.Value.Hometeam.Contains( ???? );
I'm really not sure what to pass into contains, I assume another lambda expression but what?
The closest linq expression to your loops would be:
var sb_eventdata = new Dictionary<string, string>{ {"a", "a"}, {"b", "b"}};
var final_data = new Dictionary<string, string>{{"a", "a"}, {"b", "b"}, {"c","c"}};
var result =
// first loop
sb_eventdata.Select(s =>
// second loop
final_data.Where(f => s.Value.Equals(f.Value)))
// flatten results (returns results from the first dictionary)
.SelectMany(x => x);
You can use a linq Intersect function to find like items in a list.
Then display all like items.
var foo = sb_eventdata.Select(o => o.Value.Car).Intersect(final_data.Select(o => o.Value.Car));
foreach (var item in foo)
{
Console.Writeline("Found!");
}
I think your friend is the Join() method.
In "LinqPad style":
void Main()
{
var a = new[] {
new Car("Opel",200),
new Car("Volkswagen",300),
new Car("Audi", 500)
};
var b = new[] {
new Car("Peugeot", 180),
new Car("Seat", 300),
new Car("Volvo", 480)
};
var c = a.Join(b, ak => ak.Value, bk => bk.Value, (ak,bk) => new {A=ak.Name,B=bk.Name,ak.Value});
c.Dump();
}
// Define other methods and classes here
class Car {
public string Name;
public int Value;
public Car (string name, int value) {
Name = name;
Value = value;
}
}
If you just want to know if both dictionary share at least one value, you can use Any:
if(sb_eventdata.Any(s =>
final_data.Any(f => s.Value.Car.Equals(f.Value.Car))))
Console.WriteLine("Found!");
or with Contains:
if(sb_eventdata.Any(s => final_data.ContainsValue(s.Value)))
Console.WriteLine("Found!");
and if you want to count how many of sb_eventdata are in final_data:
sb_eventdata.Where(s => final_data.ContainsValue(s.Value)).Count();
in linq, is it possible to combine many lists (of the same type), such that two lists,
list 1 = {a,b,c} and list 2 = {x,y,z}
turns into {[1,a] , [1,b] , [1,c] , [2,x] , [2,y] , [2,z] }
where [] represents a pair containing a "list identifier"
The problem is from having decks of arbitrary cards, where each deck is a list in a collection of lists.
I'm trying to create a query such that I can select only cards in a certain deck, or cards similar to 2 or more decks.
This is probably a duplicate question, but I don't know how to search for the question further then I already have.
List<List<int>> lists;
var combined = lists.Select((l, idx) => new { List = l, Idx = idx })
.SelectMany(p => p.List.Select(i => Tuple.Create(p.Idx + 1, i)));
var list1 = new List<string>() {a,b,c};
var list2 = new List<string>() {x,y,z};
var combined = list1.Select(x => new { id = 1, v = x }).Concat(list2.Select(x => new { id = 2, v = x }));
Normally I'd suggest Enumerable.Zip for combining multiple lists, however you seem to actually want to concatenate multiple lists with a list counter.
public IEnumerable<Tuple<int,T>> Combine<T>(params IEnumerable<T>[] lists) {
return lists.Select((x,i) => x.Select(y => Tuple.Create(i+1,y))).SelectMany (l =>l);
}
UPDATE
Completely missed that SelectMany has the index option so the above code can be written as
public IEnumerable<Tuple<int,T>> Combine<T>(params IEnumerable<T>[] lists) {
return lists.SelectMany((x,i) => x.Select(y => Tuple.Create(i+1,y)));
}
Then you can do
var list1 = new List<string> { "a", "b", "c" };
var list2 = new List<string> { "x", "y", "z" };
var combined = Combine(list1,list2);
Combined will be enumerable of tuples, with Item1 being the list index identifier (starting at 1) and Item2 being the value.
This method will handle multiple lists so you could just as easily call it with:
var list3 = new List<string> { "f", "g" };
var combined = Combine(list1,list2,list3);
You can merge the lists like:
var first = new List<string> {"a","b","c"};
var second = new List<string> {"x","y","z"};
var merged = first.Select(item => new { ListIndex = 1, Value = item}).ToList();
merged.AddRange(second.Select(item => new { ListIndex = 2, Value = item});
//or use concat
var merged = first.Select(item => new { ListIndex = 1, Value = item});
.Concat(second.Select(item => new { ListIndex = 2, Value = item});
Alternatively if you have the sources in something like:
List<List<string>> lists = new List<List<string>>
{
new List<string> {"a","b","c"},
new List<string> {"x","y","z"}
};
you can do:
var merged = lists.SelectMany((item, index) =>
item.Select(s => new { ListIndex = index, Value = s}));
Note that this will produce a 0-based list, so if you really need a 1-base list, just do ListIndex = index +1.
Also, if you will use this a lot, I would create it as an specific entity, something like
struct ListIdentValue
{
public int ListIndex {get; private set;}
public string Value {get; private set;}
public ListIdentValue(int listIndex, string value) {...}
}
Try using Concat
new[] {'a','b','c'}
.Select(v=>new Tuple<int,char>(1, v))
.Concat(
new[] {'x','y','z'}.Select(v=>new Tuple<int,char>(2, v))
)
string[] a = { "a", "b", "c" };
string[] b = { "x", "z", "y" };
var t =
(
from ai in a
select new { listNo = 1, Item = ai }
).Union
(
from bi in b
select new { listNo = 2, Item = bi }
);
or
var t =
(
from ai in a
select new object[] { 1, ai }
).Union
(
from bi in b
select new object[] { 2, bi }
);
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();