I'm trying to convert some JS into C# and i got to this piece but cant figure out what a C# equivalent would be. Hoping someone can point me in the right direction?
I just need help with the contents of these two functions. The $iterator is coded in another spot but im guessing that the C# version of the following code doesnt need it. If you need me to add it, i can.
The context these functions are being called is:
var centers = Lambda.array(Lambda.map(this.hexes,function(hex) {
return me.hexToCenter(hex);
}));
And the functions are:
var Lambda = function() { }
Lambda.array = function(it) {
var a = new Array();
var $it0 = $iterator(it)();
while( $it0.hasNext() ) {
var i = $it0.next();
a.push(i);
}
return a;
}
Lambda.map = function(it,f) {
var l = new List();
var $it0 = $iterator(it)();
while( $it0.hasNext() ) {
var x = $it0.next();
l.add(f(x));
}
return l;
}
You don't really need your own map and array methods. There is already the same functionality available, you just have to add using System.Linq; at the top of your file and you'll be able to use both Select, which is a projection method and ToArray which created an array from your collection. They are both extension methods set on IEnumerable<T>, so you can use them on almost any collection.
var centers = hexes.Select(x => me.hexToCenter(x)).ToArray();
is an equivalent of you JavaScript code:
var centers = Lambda.array(Lambda.map(this.hexes,function(hex) {
return me.hexToCenter(hex);
}));
This looks like a fairly simple C# lambda:
var centers = this.hexes.Select(hex => me.hexToCenter(hex)).ToList();
Select and ToList extension methods are provided by LINQ - you need to add using System.Linq to use them.
You probably want to go the LINQ route here.
Your map is equivalent to LINQ's Select, e.g.
var centers = this.hexes.Select(hex => me.hexToCenter(hex)).ToArray();
The expression hex => me.hexToCenter(hex) is a lambda expression in C#, which Select uses to project this.hexes into your desired form.
ToArray() is equivalent to your Lambda.array call.
101 LINQ Samples in C# is a great resource for examples on using LINQ.
note most of the 101 samples use the query syntax as opposed to the functional syntax I've used above. They are roughly equivalent for simple cases, but being comfortable with the functional syntax shouldn't be a problem for you, coming from JS background.
Related
This question already has answers here:
C# Lambda expressions: Why should I use them?
(17 answers)
Closed 9 years ago.
Can anyone give me a good explanation of how to use Lambda and give a good example. I have seen it but I dont know what it is or does.
A lambda expression is used to create an anonymous function. Here an anonymous function is assigned to a delegate variable:
Func<int, int> increase = (a => a + 1);
You can then use the delegate to call the function:
var answer = increase(41);
Usually lambda expressions are used to send a delegate to a method, for example sending a delegate to the ForEach method so that it's called for each element in the list:
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.ForEach(n => Console.WriteLine(n));
I did a post a while back which I hope may be of some use: http://www.dontcodetired.com/blog/?tag=/lambda+expressions
A Lambda is simply a delegate, its an anonymous function that you can create for later execution.
A Lambda Expression is an uncompiled delegate in the form of an Expression Tree that you can manipulate before compiling and executing.
http://msdn.microsoft.com/en-us/library/bb397687.aspx
Perhaps I'm being a bit simplistic, but, if I were you, to start with I'd just consider lambdas as a nice way to shorten code by removing things like nested foreach loops or top n elements.
So if you're running round hotels to find some with cheap rooms you could (assuming hotels in IEnumerable):
cheapHotels = hotels.Where(h => h.PriceFrom < 50)
Once this starts to click you can move onto something more complex, this is a random method that I can find in my current project using lambdas (probably nicked from somewhere else!):
private T DeserializeObject<T>(XmlDocument xDoc, string typeName)
{
Type type = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Single(t => t.FullName == typeName);
object o;
var serializer = new XmlSerializer(typeof(T));
using (TextReader tr = new StringReader(xDoc.InnerXml))
{
o = serializer.Deserialize(tr);
tr.Close();
}
return (T)o;
}
I'm trying to re-write an application from .net to Scala, mainly for practice and I've come across this Linq expression that I don't know how to work with. linq is also foreign to me so I'm a little bit out of my depth.
private void DeleteItems(AmazonSimpleDB client, IEnumerable<string> itemNames)
{
var deleteableItems = from n in itemNames select new DeleteableItem()
{
ItemName = n
}
}
I'm looking at some other answers using maps but so far have been unsuccessful, thank you for any help.
It will look something like this:
var deleteableItems = itemNames.map(n -> new DeleteableItem(ItemName = n))
Note that your DeleteableItem should have constructor with ItemName parameter.
I am using the latest version of Mongo C# driver which uses a lot of Async and builder pattern. Which is nice. I am trying to convert SQL where clauses into Mongo FilterDefinition object.
Any idea how to handle "contains"?
like:
where x contains 'ABC'
In order to achieve that in V2 API, use the `Filter.Regex':
var collection = db.GetCollection<BsonDocument>("collection");
var filter = Builders<BsonDocument>.Filter.Regex("fieldName", new BsonRegularExpression(".*fieldValue.*"));
var data = await (await coll.FindAsync<BsonDocument>(filter).ConfigureAwait(false)).ToListAsync();
//continue process data
If x is a string, you could do so with a simple regex. For the 2.0 driver, you can manually create the FilterDefinition:
FilterDefinition<BsonDocument> filter = "{ x : { $regex : /ABC/ } }";
Or build the filter use the Builder:
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Matches("x", "ABC");
Then you can use the filter in your query:
using (var cursor = await collection.Find(filter).ToCursorAsync())
{
// ...
}
I was able to get this working using Filter.AnyIn like so
var filter = Builders<BsonDocument>.Filter.AnyIn("x", new List<string> { "ABC" });
This works if you're looking for multiple values too, just add them to the list.
First, I highly recommend taking MongoDB University's .NET course (from Mongo itself). It's really thorough, and covers your question (and more) in depth.
Second, I assume that x is an array in your example.
MongoDB correctly handles polymorphism with arrays. If you have a class Post with an array of Tags, you can filter where Tag = ABC.
If you're using the C# linq methods, that looks like .Find(p => p.Tags == "ABC"). If you're using BsonDocument, that looks like new BsonDocument().Add("Tags", "ABC").
I have another way which I don't love but it works. The answer that is marked correct is half wrong (Matches is a method of Builders). In this example the / act like a % in a sql query LIKE statement. I'm still looking for a better way and will update if I find one that is more Equals filter below.
List<yourobject> someList = await collection.Find("{ x: /Test/ }").ToListAsync();
var filter = Builders<yourobject>.Filter.Eq("x", "ABC");
List<yourobject> someList = await collection.Find(filter).ToListAsync();
If you want to just search input text you need to replace regex special characters.
Regex.Escape will ensure that these characters are processed literally rather than as metacharacters. Otherwise input text can be used to query regex patterns which is probably not what is required.
var text = "ABC";
var filter = Builders<BsonDocument>.Filter.Regex("x", BsonRegularExpression.Create(Regex.Escape(text)));
If you need case insensitive check. Then you can pass case insensitive regex to BsonRegularExpression.Create:
var text = "ABC";
var escapeText = Regex.Escape(text);
var regex = new Regex(escapeText, RegexOptions.IgnoreCase);
var filter = Builders<BsonDocument>.Filter.Regex("x", BsonRegularExpression.Create(regex));
I tried to use expandoobjects in LINQ queries to have the ability to query against properties that are created during runtime, for example the headers from a csv file. It all worked fine if typing the LINQ query direct in the code as in the example:
// initialize testdata
List<ExpandoObject> hans = new List<ExpandoObject>();
string[] names = {"Apfel", "Birne", "Banane", "Orange"};
int[] ids = { 1, 2, 3, 4 };
for (int i = 0; i < 4; i++)
{
dynamic horst = new ExpandoObject();
((IDictionary<string, object>)horst).Add("Fruit", names[i]);
((IDictionary<string, object>)horst).Add("ID", ids[i]);
hans.Add(horst);
}
// try some LINQ queries, both are working as intended
var klaus = from dynamic x in hans where x.ID < 3 select x;
//var klaus = hans.Where(x => x.ID < 3).Select(x => x);
Then i tried to read the query from the commandline and create a dynamic LINQ query using a slighty modified version of the evaluant linq compiler.
string expression = System.Console.ReadLine();
LinqCompiler lc = new LinqCompiler(expression);
lc.AddSource<ExpandoObject>("hans", hans);
IEnumerable<ExpandoObject> klaus = (IEnumerable<ExpandoObject>)lc.Evaluate();
As long as as i donĀ“t use WHERE or ORDER BY statements, everything is fine, but if any WHERE or ORDER BY is included in the query, i get an error when compiling the codedom code in the linq compiler: CS1963: An expression tree may not contain a dynamic operation.
The code for the query is created using the following line:
doRequestMethod.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(Query)));
I suppose that the codedom compiler is building the expression tree in some way different to the way a direct typed in LINQ query is parsed. Any idea to get this to work would be appretiated, including other ideas to dynamically create queries for runtime-generated objects.
To get the error you're getting, I had to fix the LINQ Compiler to support dynamic, by telling it to use C# 4.0 and add a reference to Microsoft.CSharp.dll, so I assume you have done the same.
The problem is a source in LINQ compiler can be any collection, including IQueryable<T>. And if IQueryable<T> is supposed to work correctly, you actually need to treat it as IQueryable<T>, not IEnumerable<T>. The way LINQ compiler solves this is that it treats any source as IQuerybale<T>by using the AsQueryable() extension method.
This means the generated code looks like this:
public object DoRequest(System.Linq.IQueryable<System.Dynamic.ExpandoObject> hans) {
return from dynamic x in hans where x.ID < 3 select x;
}
The problem with this code is that tries to use IQuerybale<T> versions of LINQ methods, that use Expressions. And, as the error message tells you, Expressions don't support dynamic.
I think the easiest way to fix this is to modify LINQ Compiler to use IEnumerable<T>, instead of IQuerybale<T> by changing the AddSource() into:
public void AddSource<T>(string name, IEnumerable<T> source)
{
this.sources.Add(new SourceDescription(name, typeof(IEnumerable<T>), source));
}
Of course, this means it won't work well for database queries, but you can't make database queries work with dynamic anyway.
I have two JSON objects here, generated through the Google Search API. The URL's of these objects can be found below.
http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=hello%20world&rsz=large
http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=hello%20world&rsz=large&start=8
As you can see the first URL returns the first eight results, whilst the second one returns the next eight. Instead of checking these results separately I'd like to programmatically merge them into one JSON object and pass them through as the first sixteen results.
I've attempted this with a couple of extremely simple JSON objects, but what Google returns is still a bit above my head, so I'm hoping for a bit of help with doing such a thing.
As far as I've been told it is not against Google's Terms of Service to merge two objects into one, only that these always go through as two results (which they will). Some friends have pointed me in the direction of automated tools that are capable of doing such things, but I'm yet to find such a tool.
I'm currently working within ASP.NET so C# or VB.NET code is great, but I'm somewhat language independent so any help in any language will be very much appreciated.
Can anyone provide any help and/or advice on doing such a thing?
EDIT: These results will eventually be saved to a database, so any server-side methods would be fantastic, even if it means putting them straight into a table for dealing with later.
function MergeJSON (o, ob) {
for (var z in ob) {
o[z] = ob[z];
}
return o;
}
This looks a lot like the code from Elliot, but is a bit safer in some conditions. It is not adding a function to the object, which could lead to some syntax problems, when used in with a framework like Extjs or jQuery. I had the problem that it gave me problems in the syntax when used in an event listener. But credits go to Elliot, he did the job.
Use this as following:
a = {a : 1}
b = {b : 2}
c = {c : 3}
x = MergeJSON ( a, b);
x = MergeJSON ( x, c);
result : x == {a : 1, b : 2, c : 3}
Thank you Elliot
Object.prototype.merge = (function (ob) {
var o = this;
var i = 0;
for (var z in ob) {
if (ob.hasOwnProperty(z)) {
o[z] = ob[z];
}
}
return o;
})
var a = {a:1}
var b = {b:2}
var c = a.merge(b); // === {a:1,b:2}
Rather than merge the two results together, I just decided to parse them, then link those two together. In the end there was really no need to merge the two together when they could be easily joined within a database.
If you are up to a client side solution(JavaScript actually) what about trying the "unite" function I have written: http://code.google.com/p/av-jslib/source/browse/js/aV.ext.object.js#36
With Jquery you could do this!
a = $.extend({a:1}, {b:2});
result: Object { a=1, b=2}
http://api.jquery.com/jQuery.extend/
Also, if you really want to do the results manipulation server-sided, this article seems to give a pretty reasonable walkthrough of the process.
I'm not sure how you'd merge these things completely, given that there's a lot of extra data in each apart from the results themselves, but if you just want a JavaScript array containing all 16 results, this should work...
var responses = [GetJsonObjectFromThatUriUsingJqueryOrSomething(),
GetJsonObjectFromThatOtherUriUsingJqueryOrSomething()];
// Probably want to check for success
// and ensure that responses[i].responseData.results is valid.
var results = [];
for (var i = 0; i < responses.length; ++i)
{
results = results.concat(responses[i].responseData.results);
}
To make it more neat, you can add the merge function to the JSON object.
This is the solution from Johan van de Merwe based on Elliot's answer, added to the actual JSON object.
// Extend JSON object
JSON.merge = function (o,ob) {
for (var z in ob) {
o[z] = ob[z];
}
return o;
}
json3 = JSON.merge(json1,json2);