Simple scenario :
var d = new Dictionary<int, List<int>>();
Dictionary<int, IEnumerable<int>> d2 = d.ToDictionary(
kv => kv.Key,
kv => kv.Value // <-- the problem
);
.
ERROR CS0029 : Cannot implicitly convert from List<string> to IEnumerable<string>
My (shameful) workaround :
Dictionary<int, IEnumerable<int>> d2 = d.ToDictionary(
kv => kv.Key,
kv => kv.Value.Where(x => true) // <-- back to being IEnumerable
);
I'm not bold enough to try this and face unforeseen consequences :
Dictionary<int, IEnumerable<int>> d2 = d.ToDictionary(
kv => kv.Key,
kv => (IEnumerable<int>)kv.Value // <-- explicit cast
);
Any advice?
Dictionary<int, IEnumerable<int>> d2 = d.ToDictionary(
kv => kv.Key,
kv => kv.Value.Where(x => true).AsEnumerable() // <--
);
Related
The code below will produce a uri with the POCO name included
(https://demo.com/query/slug1/myIndexName/myPoco/_search).
What I need is just https://demo.com/query/slug1/myIndexName/_search
var node = new Uri("https://demo.com/query/slug1/");
var settings = new ConnectionSettings(node, defaultIndex: "myIndexName");
int skipCount = 0;
int takeSize = 100;
var client = new ElasticClient(settings);
do
{
var searchResults = client.Search<myPoco>(x => x.Index("myIndexName")
.Query(q => q
.Bool(b => b
.Must(m =>
m.Match(mt1 => mt1.OnField(f1 => f1.status).Query("New")))))
.Skip(skipCount)
.Take(takeSize));
foundStuff = (List<myPoco>)searchResults.Documents;
foreach (foundThing item in searchResults.Documents)
{
//DO stuff
}
skipCount = skipCount + takeSize;
} while (foundStuff.Count == 100);
Am I missing something simple, or is this AFU?
It's not AFU :) NEST will infer the type name to include in the URI from the generic parameter type passed to Search<T>(). You can override this easily enough using .AllTypes()
var searchResults = client.Search<myPoco>(x => x
.Index("myIndexName")
// specify all types
.AllTypes()
.Query(q => q
.Bool(b => b
.Must(m =>
m.Match(mt1 => mt1.OnField(f1 => f1.status).Query("New")))))
.Skip(skipCount)
.Take(takeSize)
);
Bear in mind though that this will now search across all types in the index and attempt to deserialize each to a myPoco type.
In response to your comment, index and type are two different concepts so if you named the type the same as the index, you would still get ~/{index}/{type}/_search. With NEST
You can map a default index for a type with .MapDefaultTypeIndices() on connection settings
var settings = new ConnectionSettings(new Uri("http://localhost:9200"))
.MapDefaultTypeIndices(d => d.Add(typeof(myPoco), "myIndexName"));
and similarly, you can map a default type name for a type
var settings = new ConnectionSettings(new Uri("http://localhost:9200"))
.MapDefaultTypeNames(d => d.Add(typeof(myPoco), "myType"));
You could abuse this to map string.Empty as the default type name for your type to get the URIs that you want
I have a list of objects with a constant value property for each type. For example:
ObjectA : { Value: 5 }
ObjectB : { Value: 15 }
ObjectC : { Value: 2 }
In my object list, these objects can occur multiple times:
List<object> objects = new List<object> { ObjectA, ObjectA, ObjectB, ObjectC, ObjectC, ObjectC};
Now I want to sum all objects (by property Value), but I want a list of distinct objects like:
List<object> objects = new List<object> { ObjectA, ObjectB, ObjectC };
How can I realise that? Distinct() does not work in this case.
Thanks in advance!
Yheeky
Expanding a little on Gert Arnold's answer, here is how to use dynamics to get the sum from the distinct list of object types:
var a1 = new ObjectA(); //Value is 5
var a2 = new ObjectA(); //Value is 5
var b = new ObjectB(); //Value is 15
var c = new ObjectC(); //Value is 2
var list = new List<dynamic> { a1, a2, b, c };
var result = list
.GroupBy(d => d.GetType())
.Select(g => g.First())
.Sum(d => d.Value);
The resulting value is 22, not 27.
You can split this into separate steps if you want to maintain the list of distinct object types.
You can group the objects by their type and take the first of each group:
var result = objects.GroupBy(o => o.GetType())
.Select(g => g.First());
I'm not sure what you mean by sum all objects (by property Value), but you could also do this:
var result = objects
.GroupBy(o => o.GetType())
.Select(g => new
{
Object = g.Key.Name,
Sum = g.Sum(x => (int)(g.Key.GetProperty("Value")
.GetValue(x)))
});
Which will give an output like:
ObjectA 12
ObjectB 60
ObjectC 24
My requirement is to order table according to a column in runtime. So I went through the path of parameter expression. I am able to achieve it when all the columns are present in single table. Here is my piece of code:
My requirement is to order table according to the buildStatusOrder during run time:
List<BuildStatusEnum> buildStatusOrder = new List<BuildStatusEnum>
{
BuildStatusEnum.h,
BuildStatusEnum.f,
BuildStatusEnum.a
};
ParameterExpression parameterExpression = Expression.Parameter(typeof(companyQueue));
MemberExpression memberExpression = Expression.PropertyOrField(parameterExpression, "buildStatusID");
MemberExpression valueExpression = Expression.Property(memberExpression, "Value");
Expression orderByExpression = Expression.Constant(buildStatusOrder.Count);
for (int statusIndex = buildStatusOrder.Count - 1; statusIndex >= 0; statusIndex--)
{
ConstantExpression constantExpression = Expression.Constant((int)buildStatusOrder[statusIndex]);
ConstantExpression indexConstantExpression = Expression.Constant(statusIndex);
BinaryExpression equalExpression = Expression.Equal(valueExpression, constantExpression);
orderByExpression = Expression.Condition(equalExpression, indexConstantExpression, orderByExpression);
}
MemberExpression hasValueExpression = Expression.Property(memberExpression, "HasValue");
ConditionalExpression nullCheckExpression = Expression.Condition(hasValueExpression, orderByExpression, Expression.Constant(buildStatusOrder.Count));
var orderByLambda = Expression.Lambda<Func<companyQueue, int>>(nullCheckExpression, parameterExpression);
using (KapowContext context = new KapowContext())
{
var queue = context.companyQueues
.Where(cq => cq.u.s.cq.userID == Utilities.Authentication.UserId)
.Where(cq => buildStatusOrder.Contains((BuildStatusEnum)cq.u.s.cq.buildStatusID))
.OrderBy(o => o.u.se.segmentId)
.ThenBy(orderByLambda)
This works fine. I have to display an additional column. It is from another table. So I joined tables. My lambda expression now looks like this:
var queue = context.companyQueues
.Join(context.abcd, cq => cq.robotID, r => r.robotId, (cq, r) => new { cq, r })
.Join(context.efgh, s => s.r.segmentId, se => se.segmentId, (s, se) => new { s, se })
.Join(context.hijk, u => u.s.cq.userID, us => us.userID, (u, us) => new { u, us })
.Where(cq => cq.u.s.cq.userID == Utilities.Authentication.UserId)
.Where(cq => buildStatusOrder.Contains((BuildStatusEnum)cq.u.s.cq.buildStatusID))
.OrderBy(orderByLambda)
Now my orderbyLambda is not working. I am getting the following error:
'System.Linq.Queryable.ThenBy<TSource,TKey>(System.Linq.IOrderedQueryable<TSource>, System.Linq.Expressions.Expression<System.Func<TSource,TKey>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
I am trying to create parent child relationships using NEST client for C#. Here is the code I have. I am using elasticsearch 1.1.1 and this code seems to be adding the testp1 object to the testparent index but it is not adding any objects to the testchild index. If I do not pass a parent using the index parameters it seems to work fine. Any help regarding this is appreciated.
private static void LoadTestData()
{
var esClient = CreateNESTConnection();
esClient.MapFluent<testparent>(x => x
.IndexName("testdb")
.TypeName("testparent")
.IdField(y => y.SetPath("Id"))
.Properties(cprops => cprops
.String(a => a.Name("id"))
.Number(a => a.Name("parentid").Type(NumberType.#long))
.Number(a => a.Name("prop1").Type(NumberType.#long))
.Number(a => a.Name("prop2").Type(NumberType.#long))
.Boolean(a => a.Name("checkflag"))
));
esClient.MapFluent<testchild>(x => x
.IndexName("testdb")
.TypeName("testchild")
.SetParent("testparent")
.Properties(cprops => cprops
.Number(a => a.Name("dockey").Type(NumberType.#long))
.Number(a => a.Name("docvalue").Type(NumberType.#float))
));
testparent testp1 = new testparent();
testp1.checkflag = true;
testp1.id = "7";
testp1.parentid = 77;
testp1.prop1 = 1;
testp1.prop2 = 2;
testchild testc1 = new testchild();
testc1.dockey = 100;
testc1.docvalue = 111;
testchild testc2 = new testchild();
testc2.dockey = 100;
testc2.docvalue = 111;
esClient.Index(testp1, "testdb");
IndexParameters parameters = new IndexParameters();
parameters.Parent = "7";
var t = esClient.Index(testc1, "testdb", parameters);
Console.WriteLine(t.OK);
t = esClient.Index(testc2, "testdb", parameters);
Console.WriteLine(t.OK);
}
here is the problem:
I have a column with the topics in the format: "boston | new york | chicago". The names can be different and number of the topics can vary in the records.
What I need to come up with is the collection of the same names with the count of those names.
This is what I have done:
var splitted = queryResult.Select(x => x.TopicData);
List<string> lstOfTopics = new List<string>();
foreach (var element in splitted)
{
string[] splitedTopics = element.Split('|');
lstOfTopics.AddRange(splitedTopics);
}
var groupedTopics = lstOfTopics.GroupBy(x => x).Select(group => new {key = group.Key, count = group.Count()}).AsEnumerable();
seems a lot of code for a simple task. any ideas how to simplify this?
thanks!
You can construct the list using SelectMany and ToList:
List<string> lstOfTopics = splitted.SelectMany(x => x.Split('|')).ToList();
You can also omit the construction of the list entirely:
var groupedTopics = queryResult
.SelectMany(x => x.TopicData.Split('|'))
.GroupBy(x => x)
.Select(group => new { group.Key, Count = group.Count()});
var groups = queryResult
.SelectMany(t => t.TopicData.Split('|')
.GroupBy(n => n)
.Select(g => new { Key = g.Key, Count = g.Count() });
query syntax can be nice and compact:
var topics =
from qr in queryResult
from topic in qr.TopicData.Split('|')
group topic by topic into g
select new { Topic = g.Key, Count = g.Count() };
If you want just the unique topics, but not their counts...
List<string> topicList = topics.Select(item => item.Topic);