I am having trouble trying to get iterators for inner sub-containers.
Basically imagine this simplified code:
typedef map<string, map<string, map> > double_map;
double_map dm;
.. //some code here
for(double_map::iterator it = dm.begin(); it != dm.end(); it++){
//some code here
it->first // string
it->second // <---- this is the 2nd map, how do i get its iterator so I can wrap it
//in a for loop like above?
}
I need to be able to do this without using typedefs for every single inner container, is there a way to get an iterator for the inner container? I have structure that has 4 inner containers and I need to iterate through them all.
(Beware, nothing compiled in the following snippets.)
for(double_map::iterator it = dm.begin(); it != dm.end(); it++){
//some code here
it->first; // string
it->second.begin();
it->second.end();
}
Edit: I fI understand your comment correctly, you want to get at the type of the iterators of the inner map. If that is so, here's one way:
double_map::mapped_type::iterator inner_iter = it->second.begin();
Off the top of my head, this should work, too:
double_map::value_type::second_type::iterator inner_iter = it->second.begin();
Simple:
typedef map<string, map> inner_map; //Typedef for readability
typedef map<string, inner_map > double_map;
double_map dm;
.. //some code here
for(double_map::iterator it = dm.begin(); it != dm.end(); it++){
//some code here
it->first // string
inner_map &innerMap(it->second); //Reference to the inner map for readability
for(inner_map::iterator it2 = innerMap.begin(); it2 != innerMap.end(); ++it2) {
//Do whatever you like
}
}
Related
Is there any way to iterate in reverse on a LLVM Function. I've checked the docs
but can't seem to find any member typedef for iterating Basic blocks ( in a function ) in reverse.
Any help will be appreciated.
Thanks,
Malhar
for (BasicBlock::reverse_iterator i = BB->rbegin(), e = BB->rend(); i != e; ++i)
{
// your code
}
I think you can call Function::getBasicBlockList() and then use .rbegin() and rend() on that list.
Sharing the working code snippet based on #arrowd suggestions:
auto bbList = &(func_ptr->getBasicBlockList()); //fetch the pointer of the list
errs()<<"reverse \n";
for(auto bb = bbList->rbegin(); bb != bbList->rend(); bb++) {
b = &(*bb);
errs() << b->getName()<<", ";
}
What is the sequence of printing the basic block names , in case there are multiple predecessors and successors ?
opposite of Reverse Post Order i.e Post - order (while iterating in reverse fashion)
You can use llvm::reverse() from StlExtras.h to iterate containers in reverse order.
When adding a derived column to a data flow with ezAPI, I get the following warnings
"Add stuff here.Inputs[Derived Column Input].Columns[ad_zip]" on "Add
stuff here" has usage type READONLY, but is not referenced by an
expression. Remove the column from the list of available input
columns, or reference it in an expression.
I've tried to delete the input columns, but either the method is not working or I'm doing it wrong:
foreach (Microsoft.SqlServer.Dts.Pipeline.Wrapper.IDTSInputColumn100 col in derFull.Meta.InputCollection[0].InputColumnCollection)
{
Console.WriteLine(col.Name);
derFull.DeleteInputColumn(col.Name);
}
I have the following piece of code that fixes the problem.
I got it from a guy called Daniel Otykier. So he is propably the one that should be credited for it... Unlesss he got it from someone else :-)
static public void RemoveUnusedInputColumns(this EzDerivedColumn component)
{
var usedLineageIds = new HashSet<int>();
// Parse all expressions used in new output columns, to determine which input lineage ID's are being used:
foreach (IDTSOutputColumn100 column in component.GetOutputColumns())
{
AddLineageIdsFromExpression(column.CustomPropertyCollection, usedLineageIds);
}
// Parse all expressions in replaced input columns, to determine which input lineage ID's are being used:
foreach (IDTSInputColumn100 column in component.GetInputColumns())
{
AddLineageIdsFromExpression(column.CustomPropertyCollection, usedLineageIds);
}
var inputColumns = component.GetInputColumns();
// Remove all input columns not used in any expressions:
for (var i = inputColumns.Count - 1; i >= 0; i--)
{
if (!usedLineageIds.Contains(inputColumns[i].LineageID))
{
inputColumns.RemoveObjectByIndex(i);
}
}
}
static private void AddLineageIdsFromExpression(IDTSCustomPropertyCollection100 columnProperties, ICollection<int> lineageIds)
{
int lineageId = 1;
var expressionProperty = columnProperties.Cast<IDTSCustomProperty100>().FirstOrDefault(p => p.Name == "Expression");
if (expressionProperty != null)
{
// Input columns used in expressions are always referenced as "#xxx" where xxx is the integer lineage ID.
var expression = expressionProperty.Value.ToString();
var expressionTokens = expression.Split(new[] { ' ', ',', '(', ')' });
foreach (var c in expressionTokens.Where(t => t.Length > 1 && t.StartsWith("#") && int.TryParse(t.Substring(1), out lineageId)))
{
if (!lineageIds.Contains(lineageId)) lineageIds.Add(lineageId);
}
}
}
Simple but not 100% Guaranteed Method
Call ReinitializeMetaData on the base component that EzApi is extending:
dc.Comp.ReinitializeMetaData();
This doesn't always respect some of the customizations and logic checks that EzAPI has, so test it carefully. For most vanilla components, though, this should work fine.
100% Guaranteed Method But Requires A Strategy For Identifying Columns To Ignore
You can set the UsageType property of those VirtualInputColumns to the enumerated value DTSUsageType.UT_IGNORED using EzApi's SetUsageType wrapper method.
But! You have to do this after you're done modifying any of the other metadata of your component (attaching other components, adding new input or output columns, etc.) since each of these triggers the ReinitializeMetaData method on the component, which automatically sets (or resets) all UT_IGNORED VirtualInputColumn's UsageType to UT_READONLY.
So some sample code:
// define EzSourceComponent with SourceColumnToIgnore output column, SomeConnection for destination
EzDerivedColumn dc = new EzDerivedColumn(this);
dc.AttachTo(EzSourceComponent);
dc.Name = "Errors, Go Away";
dc.InsertOutputColumn("NewDerivedColumn");
dc.Expression["NewDerivedColumn"] = "I was inserted!";
// Right here, UsageType is UT_READONLY
Console.WriteLine(dc.VirtualInputCol("SourceColumnToIgnore").UsageType.ToString());
EzOleDbDestination d = new EzOleDbDestination(f);
d.Name = "Destination";
d.Connection = SomeConnection;
d.Table = "dbo.DestinationTable";
d.AccessMode = AccessMode.AM_OPENROWSET_FASTLOAD;
d.AttachTo(dc);
// Now we can set usage type on columns to remove them from the available inputs.
// Note the false boolean at the end.
// That's required to not trigger ReinitializeMetadata for usage type changes.
dc.SetUsageType(0, "SourceColumnToIgnore", DTSUsageType.UT_IGNORED, false);
// Now UsageType is UT_IGNORED and if you saved the package and viewed it,
// you'll see this column has been removed from the available input columns
// ... and the warning for it has gone away!
Console.WriteLine(dc.VirtualInputCol("SourceColumnToIgnore").UsageType.ToString());
I was having exactly your problem and found a way to solve it. The problem is that the EzDerivedColumn has not the PassThrough defined in it's class.
You just need to add this to the class:
private PassThroughIndexer m_passThrough;
public PassThroughIndexer PassThrough
{
get
{
if (m_passThrough == null)
m_passThrough = new PassThroughIndexer(this);
return m_passThrough;
}
}
And alter the ReinitializeMetadataNoCast() to this:
public override void ReinitializeMetaDataNoCast()
{
try
{
if (Meta.InputCollection[0].InputColumnCollection.Count == 0)
{
base.ReinitializeMetaDataNoCast();
LinkAllInputsToOutputs();
return;
}
Dictionary<string, bool> cols = new Dictionary<string, bool>();
foreach (IDTSInputColumn100 c in Meta.InputCollection[0].InputColumnCollection)
cols.Add(c.Name, PassThrough[c.Name]);
base.ReinitializeMetaDataNoCast();
foreach (IDTSInputColumn100 c in Meta.InputCollection[0].InputColumnCollection)
{
if (cols.ContainsKey(c.Name))
SetUsageType(0, c.Name, cols[c.Name] ? DTSUsageType.UT_READONLY : DTSUsageType.UT_IGNORED, false);
else
SetUsageType(0, c.Name, DTSUsageType.UT_IGNORED, false);
}
}
catch { }
}
That is the strategy used by other components. If you want to see all the code you can check my EzApi2016#GitHub. I'm updating the original code from Microsoft to SQL Server 2016.
Actually I've parsed a website using htmlparser and I would like to find a specific value inside the parsed object, for example, a string "$199", and keep tracking that element(by periodic parsing) to see the value is still "$199" or has changed.
And after some painful stupid searching using my eyes, I found the that string is located at somewhere like this:
price = handler.dom[3].children[3].children[3].children[5].children[1].
children[3].children[3].children[5].children[0].children[0].raw;
So I'd like to know whether there are methods which are less painful? Thanks!
A tree based recursive search would probably be easiest to get the node you're interested in.
I've not used htmlparser and the documentation seems a little thin, so this is just an example to get you started and is not tested:
function getElement(el,val) {
if (el.children && el.children.length > 0) {
for (var i = 0, l = el.children.length; i<l; i++) {
var r = getElement(el.children[i],val);
if (r) return r;
}
} else {
if (el.raw == val) {
return el;
}
}
return null;
}
Call getElement(handler.dom[3],'$199') and it'll go through all the children recursively until it finds an element without an children and then compares it's raw value with '$199'. Note this is a straight comparison, you might want to swap this for a regexp or similar?
I have a specific ViewBag property that I would like to set at the ViewStart level. Ideally, I would like to be able to override that property on a page basis, if necessary. Is this possible? If so, how do I access the ViewBag property within a ViewStart page?
There are two way to do this:
Use the PageData property (it's something more applicable to ASP.NET WebPages and seldom used in MVC)
Set:
#{
PageData["message"] = "Hello";
}
Retrieve
<h2>#PageData["message"]</h2>
Try to find the view instance (the code is a bit dirty, but it does give you access directly to ViewBag/ViewData
Set:
#{
var c = this.ChildPage;
while (c != null) {
var vp = c as WebViewPage;
if (vp != null) {
vp.ViewBag.Message = "Hello1";
break;
}
c = c.ChildPage;
}
}
Retrieve: as per usual
<h2>#ViewBag.Message</h2>
My appologies upfront for the lengthy question. I made quite an effort to make my question as clear as possible in one go. Please bear with me. ;o) any help will be greatly appreciated!
I have the classes Branch and Text:
class Branch
int ID
Text WebDescription
and a bunch of other properties
class Text
int ID
string UK
string NL
string FR
string IT
and a bunch of other properties as well
I want to only display the ID of the branch and its description in the appropriate language. I want only one query (no extra round trips) which retrieves only two fields (not the whole object).
I found three solutions
Via the object model in the query
// good: no round trips
// good: clean sql
// bad: impossible to use the currentUserLanguage parameter
var lang = "NL";
var dbProject = new ProjectDataContext();
var query = from b in dbProject.GetTable<Branch>()
select new
{
b.ID,
WebDescription = b.WebDescriptionObject.NL // <-- problem
};
var text = query.First().WebDescription;
Via the object model after the query
// good: no round trips (eager loading of text object)
// good: possible to use the currentUserLanguage parameter
// bad: loads the *whole* branch and text object, not just two fields
var lang= "NL";
var dbProject = new ProjectDataContext();
var query = from b in dbProject.GetTable<Branch>()
select new
{
b.ID,
WebDescription = b.GetWebDescriptionAsString(lang)
};
var text = query.First().WebDescription;
Using an expression
// good: I have the feeling I am on the right track
// bad: This doesn't work :o( throws an exception
var lang= "NL";
var dbProject = new ProjectDataContext();
var query = from b in dbProject.GetTable<Branch>()
select new
{
b.ID,
WebDescription = b.GetWebDescriptionAsExpression(lang)
};
var text = query.First().WebDescription;
Here is code for the two methods GetWebDescriptionAsString and GetWebDescriptionAsExpression.
public string GetWebDescriptionAsString(string lang)
{
if (lang== "NL") return WebDescriptionObject.NL;
if (lang== "FR") return WebDescriptionObject.FR;
if (lang== "IT") return WebDescriptionObject.IT;
return WebDescriptionObject.UK;
}
public Expression<Func<Branch, string>> GetWebDescriptionAsExpression(string lang)
{
if (lang== "NL") return b => b.WebDescriptionObject.NL;
if (lang== "FR") return b => b.WebDescriptionObject.FR;
if (lang== "IT") return b => b.WebDescriptionObject.IT;
return b => b.WebDescriptionObject.UK;
}
Without really answering the question, the cleanest approach would be to change the Text structure into a more normalized form like:
Text
ID
TextTranslation
ID
TextID
Lang
TextValue
where each text has a number of translations, one for each language.
The query would become something like:
var q =
from branch in dbProject.Branches
join text in dbProject.Texts on branch.TextID = text.ID
join translation in dbProject.TextTranslations on text.ID = translation.TextID
where translation.Lang == lang
select new
{
branch.ID,
WebDescription = translation.TextValue
};
This approach has other advantages as well, for example adding a new language will not change the model structure.
This would be very easy to do if you used a stored procedure. Are you opposed to using SP's as a solution?
If a stored procedure works, then I am happy to use it.
Thank you for you prompt reply.
I made a quick attempt. The UDF was already there, I just didn't know how to use it. The performance dropped significantly. The first solution is 3 times faster. In my understanding, this approach would require extra round trips to the database. Is that correct?
var query = from b in dbProject.GetTable<Branch>()
select new
{
b.ID,
WebDescription = db.fGetText(b.WebDescriptionID, (currentUserLanguage))
};
Without understanding your whole problem
create a stored procedure like this:
CREATE PROCEDURE spGetTheTextINeed #Language char(2), #BranchID int
AS
/* I don't know how your database is structured so you need to write this */
SELECT MyText from MyTable WHERE Language=#Language and Branch=#BranchID
Then you need to add the sp to your DBML and then you can just call the sp you need with the appropriate parameters:
var query = myDataContext.spGetTheTextINeed("NL",[your branch number])
Dim str As String
str = query.MyText
The code above is not to be exact - I don't understand your full requirements but this should get you started.