Grouping and sorting ObservableCollection - observablecollection

I am trying to iterate through a ObservableCollection grouping, but I cannot figure out the correct syntax for the foreach loop. Any thoughts?
ObservableCollection<SaleItem> list = new ObservableCollection<SaleItem>();
list.Add(new SaleItem("Beverage", "Pepsi", 3.99M));
list.Add(new SaleItem("Beverage", "Coke", 4.29M));
list.Add(new SaleItem("Clothing", "Jeans", 29.99M));
list.Add(new SaleItem("Clothing", "Shirt", 11.99M));
var foo = list.GroupBy(c => c.ItemType).AsEnumerable();
//Works, how do I iterate over it????
decimal sales = foo.FirstOrDefault().Sum(c => c.SalePrice);
// THIS IS THROWING A INVALID CAST
foreach (IEnumerable<IGrouping<string, Object>> obj in foo)
{
string f = "a";
}

Related

Lucene - Sorting Date as NumericField

While trying to sort datetime (long) numeric fields I always get a FormatException.
When converting a string to DateTime, parse the string to take the
date before putting each variable into the DateTime object.
Adding the numeric field:
doc.Add(new NumericField("creationDate", Field.Store.YES, true)
.SetLongValue(DateTime.UtcNow.Ticks);
Add sorting:
// boolean query
var sortField = new SortField("creationDate", SortField.LONG, true);
var inverseSort = new Sort(sortField);
var results = searcher.Search(query, null, 100, inverseSort); // exception thrown here
Inspecting the index, I can verify that 'creationDate' field is storing "long" values. What could be causing this exception?
EDIT:
Query
var query = new BooleanQuery();
foreach (var termQuery in incomingProps.Select(p => new TermQuery(new Term(kvp.Key, kvp.Value.ToLowerInvariant()))
{
query.Add(new BooleanClause(termQuery , Occur.Must));
}
return query;
Version: Lucene.Net 3.0.3
UPDATE:
This issue is occurring again, now with INT values.
I downloaded Lucene.Net source code and debugged the issue.
So it's somewhere in the FieldCache, when trying to parse the value "`\b\0\0\0" to Integer, which seems a bit odd.
I'm adding these values as numeric fields:
doc.Add(new NumericField(VersionNum, int.MaxValue, Field.Store.YES,
true).SetIntValue(VersionValue));
I get the exception when I'm supposed to get at least 1 hit back.
After inspecting the Index I see that the field's term is as following:
And the field text is:
EDIT:
I've hardcoded an int value and added a few segments:
doc.Add(new Field(VersionNum, NumericUtils.IntToPrefixCoded(1), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
Which resulted on storing the version field as:
And still, when I try to sort I get the parsing error:
var sortVersion = new SortField(VersionNum, SortField.INT, true);
For every exception, Lucene is trying to parse " \b\0\0\0 ".
Looking at the prefixed coded stored as string, 1 would translate to " \b\0\0\0\1 " I'm guessing?
Is Lucene probably leaving some garbage behind in the FieldCache ?
Here's a unit test that tries to capture what you're asking. The test passes. Can you explain what the difference with your code is? (posting a full failing test would help us understand what you're doing :-) )
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Lucene.Net.Search;
using Lucene.Net.Index;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.QueryParsers;
using Lucene.Net.Documents;
using Lucene.Net.Store;
namespace SO_answers
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestShopping()
{
var item = new Dictionary<string, string>
{
{"field1", "value1" },
{"field2", "value2" },
{"field3", "value3" }
};
var writer = CreateIndex();
Add(writer, item);
writer.Flush(true, true, true);
var searcher = new IndexSearcher(writer.GetReader());
var result = Search(searcher, item);
Assert.AreEqual(1, result.Count);
writer.Dispose();
}
private List<string> Search(IndexSearcher searcher, Dictionary<string, string> values)
{
var query = new BooleanQuery();
foreach (var termQuery in values.Select(kvp => new TermQuery(new Term(kvp.Key, kvp.Value.ToLowerInvariant()))))
query.Add(new BooleanClause(termQuery, Occur.MUST));
return Search(searcher, query);
}
private List<string> Search(IndexSearcher searcher, Query query)
{
var sortField = new SortField("creationDate", SortField.LONG, true);
var inverseSort = new Sort(sortField);
var results = searcher.Search(query, null, 100, inverseSort); // exception thrown here
var result = new List<string>();
var matches = results.ScoreDocs;
foreach (var item in matches)
{
var id = item.Doc;
var doc = searcher.Doc(id);
result.Add(doc.GetField("creationDate").StringValue);
}
return result;
}
IndexWriter CreateIndex()
{
var directory = new RAMDirectory();
var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
var writer = new IndexWriter(directory, analyzer, new IndexWriter.MaxFieldLength(1000));
return writer;
}
void Add(IndexWriter writer, IDictionary<string, string> values)
{
var document = new Document();
foreach (var kvp in values)
document.Add(new Field(kvp.Key, kvp.Value.ToLowerInvariant(), Field.Store.YES, Field.Index.ANALYZED));
document.Add(new NumericField("creationDate", Field.Store.YES, true).SetLongValue(DateTime.UtcNow.Ticks));
writer.AddDocument(document);
}
}
}

How to pass multiple list types as a parameter using the same method variable

I'm trying to pass multiple list types as a parameter using the same method variable and then loop through the types based on which type as been past. I tried using a generic method but it's not working. Below are pseudo/example codes. The List SAS_F_DISAGG_F and List SAS_C_DISAGG_C are SQL/Entity, and the List DisaggReportGroups is a class object. I'm trying to pass the entity lists.
protected void GetReportGroup()
{
DisaggReportGroups rptGroup = new DisaggReportGroups();
List<DisaggReportGroups> disagreportGroup = new List<DisaggReportGroups>();
disagreportGroup.Add(rptGroup);
DisaggregatedReportData disagReportData = new DisaggregatedReportData();
foreach (var reportGroup in disagreportGroup)
{
if (reportGroup.FuturesOnly == "Futures Only, " & reportGroup.Agriculture == "Agriculture")
{
List<SAS_F_DISAGG_F> futONlyDisagReportData = disagReportData.GetFuturesOnlyReportData(reportGroup.Agriculture).ToList();
CreateLongFormatReport<List<SAS_F_DISAGG_F>>(reportGroup.AgricultureFilenameFOLF, reportGroup.FuturesOnly, reportGroup.Agriculture, futONlyDisagReportData);
}
else if (reportGroup.FOCombined == "Futures and Options Combined, " & reportGroup.Agriculture == "Agriculture")
{
List<SAS_C_DISAGG_C> combinedDisagReportData = disagReportData.GetFOCombinedReportData(reportGroup.Agriculture).ToList();
CreateLongFormatReport<List<SAS_C_DISAGG_C>>(reportGroup.AgricultureFilenameFOCombinedLF, reportGroup.FOCombined, reportGroup.Agriculture, combinedDisagReportData);
}
}
}
protected void CreateFormatReport<T>(string filename, string disagCategory, string commSubGp, List<T> reportData)
{
using (FileStream fileStream = new FileStream(Server.MapPath(#"~/Includes/") + filename, FileMode.Create))
{
using (StreamWriter writer = new StreamWriter(fileStream))
{
foreach (var value in reportData)
{
string FuturesOnly = "Futures Only, ";
string FOCombined = "Futures and Options Combined, ";
string reportCategory = "";
if (disagCategory == FuturesOnly)
{
reportCategory = FuturesOnly;
}
else if (disagCategory == FOCombined)
{
reportCategory = FOCombined;
}
string row01 = String.Format("{0, -10}{1, 29}{2, 8}", value.MKTTITL.PadRight(120), "Code -", value.Conmkt);
string row02 = String.Format("{0, -10}{1, 7}{2, 14}", "Blah Blah - ", reportCategory, value.DAT1TITL);
string row03 = String.Format("{0, 3}{1, 3}{2, 8:0,0}{3, 3}{4, 8:0,0}{5, 11:0,0}{6, 11:0,0}{7, 11:0,0}{8, 11:0,0}{9, 13:0,0}{10, 11:0,0}{11, 11:0,0}{12, 13:0,0}{13, 10:0,0}{14, 9:0,0}{15, 3}{16, 8:0,0}{17, 10:0,0}", "All",
colon, value.TA01, colon, value.TA02, value.TA03, value.TA04, value.TA05, value.TA06, value.TA07, value.TA08, value.TA09, value.TA10, value.TA11, value.TA12, colon, value.TA15, value.TA16);
string row04 = String.Format("{0, 3}{1, 3}{2, 8:0,0}{3, 3}{4, 8:0,0}{5, 11:0,0}{6, 11:0,0}{7, 11:0,0}{8, 11:0.##}{9, 13:0,0}{10, 11:0,0}{11, 11:0,0}{12, 13:0,0}{13, 10:0,0}{14, 9:0,0}{15, 3}{16, 8:0,0}{17, 10:0,0}", "Old",
colon, value.TO01, colon, value.TO02, value.TO03, value.TO04, value.TO05, value.TO06, value.TO07, value.TO08, value.TO09, value.TO10, value.TO11, value.TO12, colon, value.TO15, value.TO16);
writer.Write(row01);
writer.WriteLine(row02);
writer.WriteLine(row03);
writer.WriteLine(row04);
} //end foreach
writer.Close();
} //end of stream writer
}
}
Thanks for your help.
I managed to solve this problem myself so I'm posting my solution for others that may need the same type of help. The solution is to use Reflection within the foreach iteration.
foreach (var value in ReportData)
{
//Reflection can be used
string TA01 = value.GetType().GetProperty("TA01").GetValue(value).ToString();
//...
//...
//do more stuff/coding...
}
Then in the String.Format change "value.TA01" to "TA01". Do the same for all other variables.
Hope this help.

How to bind String[] values in listview using hashmap in android?

Hi I am trying to get values using hashmap<> using .net web services in android. I have custemized adapter, I am trying to do this.
SoapObject folderResponse = (SoapObject)envelope.getResponse();
Log.i("AllFolders", folderResponse.toString());
String[] folderslist = new String[folderResponse.getPropertyCount()];
//getting values using folderslist.
ArrayList<HashMap<String, String>> hashfoldersList = new ArrayList <HashMap<String, String> >();
//But I want hashfoldersList list in my custamized adapter.
for(i=0; i<folderResponse.getPropertyCount(); i++) {
SoapObject SingleFolder = (SoapObject)folderResponse.getProperty(i);
Log.i("SingleFolder", SingleFolder.toString());
ID= SingleFolder.getProperty(0).toString();
KEY_Name = SingleFolder.getProperty(1).toString();
ParentID = SingleFolder.getProperty(2).toString();
CreatedBy= SingleFolder.getProperty(3).toString();
System.out.println(ID);
System.out.println(KEY_Name);
System.out.println(ParentID);
System.out.println(CreatedBy);
SoapPrimitive Record =(SoapPrimitive) SingleFolder.getProperty(1);
Log.i("Record", Record.toString());
{
folderslist[i] = SingleFolder.getProperty(0).toString();
}
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
org.w3c.dom.Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = (NodeList) doc.getElementsByTagName(ID);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(ID, parser.getValue(e, ID));
map.put(KEY_Name, parser.getValue(e, KEY_Name));
map.put(ParentID, parser.getValue(e, ParentID));
map.put(CreatedBy, parser.getValue(e, CreatedBy));
foldersList.add(map);
}
listview = (ListView)findViewById(R.id.listview);
adapter=new LazyAdapter(this, hashfoldersList);
//My custemized adapter.
listview.setAdapter(adapter);
listview.setOnItemClickListener(this);
}
}
Please suggest, how to get values in list using ArrayList> hashfolderlist, as I am using string[] folderlist. when I am inserting hashfolderlist, it is giving error. Please suggest. thanks
mate you should have a simple adapter to take the strings and put it inside a listview.
second you should have 2 textviews
SimpleAdapter adapter = new SimpleAdapter(this, list,
R.layout.your_activity, new String[] { "", "" },
new int[] { R.id.textview1, R.id.textView2 }
);
listView1.setAdapter(adapter);
hope it helps you!!

Convert paired lists into one-to-many lookup

I have lists (of equal length) of paired strings, call them "source" and "target". One source may map to multiple targets. Can I convert this to a lookup table (mapping a source to a list of targets) using LINQ? One (long-winded) way of doing this is:
// There may be multiple targets corresponding to each source
// as in the following example lists.
// NB. Lists are guaranteed same length
List<string> sourceNames = new List<string>() { "A", "B", "C", "A", "B", "C" };
List<string> targetNames = new List<string>() { "Z", "Y", "X", "W", "V", "U" };
// Use extension methods to make list of unique source names
List<string> uniqueSourceNames = sourceNames.Distinct().ToList<string>();
// For each unique source, make a list of the corresponding targets
Dictionary<string, List<string>> nameLookup = new Dictionary<string, List<string>>();
foreach (string sourceName in uniqueSourceNames)
{
List<string> targetsForSource = new List<string>();
for (int index = 0; index < sourceNames.Count; index++)
{
if (sourceNames[index] == sourceName)
targetsForSource.Add(targetNames[index]);
}
nameLookup.Add(sourceName, targetsForSource);
}
// Can now use the nameLookup dictionary to map a source name to a list of target names
// e.g. this returns "Z", "W"
List<string> targets = nameLookup["A"];
Is there a way to do this more efficiently using LINQ?
You can use GroupBy and ToDictionary:
var lookup = sourceNames
.Select((Source, i) => new { Target = targetNames.ElementAt(i), Source})
.GroupBy(x => x.Source)
.ToDictionary(g => g.Key, g => g.Select(x => x.Target));
Now every distinct source-string is mapped to an IEnumerable<string> targets.
foreach (var kv in lookup)
Console.WriteLine("{0} has destinations {1}"
, kv.Key
, string.Join(",", lookup[kv.Key]));
Edit: Here's the demo: http://ideone.com/b18H7X
You can use Zip and ToLookup:
var nameLookup = sourceNames
.Zip(targetNames, (x, y) => new { Source = x, Target = y })
.ToLookup(x => x.Source, x => x.Target);

How do I create an OrderBy statement using a reflected value?

I would like to create a method that orders an IEnumerable List by a given property where the property is passed into the method by a string i.e. (Mind you the first code example does not work, but the second does and is what I am trying to emulate dynamically).
string sortName = "SerialNumber";
IEnumerable<PartSummary> partList = FunctionToCreateList();
partOrderedList = partList.OrderBy(what do I stick in here);
that would be equivalent to
IEnumerable<PartSummary> partList = FunctionToCreateList();
partOrderedList = partList.OrderBy(p => p.SerialNumber);
How can I accomplish this?
Are you saying you want to pass the order by in to your method? If so, you can use this:
Expression<Func<PartSummary, bool>> orderByClause
Then you can do this:
partOrderedList = partList.OrderBy(orderByClause);
Then you can handle your order by in your business layer or wherever you wish.
Okay, update: If you want to pass in the column name as a string you can do something like as follows:
Create a static class for an extension method (reference: http://social.msdn.microsoft.com/Forums/en-US/linqprojectgeneral/thread/39028ad2-452e-409f-bc9e-d1b263e921f6/):
static class LinqExtensions
{
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string sortingColumn, bool isAscending)
{
if (String.IsNullOrEmpty(sortingColumn))
{
return source;
}
ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty);
MemberExpression property = Expression.Property(parameter, sortingColumn);
LambdaExpression lambda = Expression.Lambda(property, parameter);
string methodName = isAscending ? "OrderBy" : "OrderByDescending";
Expression methodCallExpression = Expression.Call(typeof(Queryable), methodName,
new Type[] { source.ElementType, property.Type },
source.Expression, Expression.Quote(lambda));
return source.Provider.CreateQuery<T>(methodCallExpression);
}
}
Then you can create your method:
static IQueryable<PartSummary> FunctionToCreateList()
{
IList<PartSummary> list = new List<PartSummary>();
list.Add(new PartSummary
{
Id = 1,
SerialNumber = "A",
});
list.Add(new PartSummary
{
Id = 2,
SerialNumber = "B",
});
return list.AsQueryable();
}
And then call your method:
static void Main(string[] args)
{
IQueryable<PartSummary> partOrderedList = FunctionToCreateList();
PartSummary partSummary = new PartSummary();
string sortBy = "Id";
partOrderedList = partOrderedList.OrderBy(sortBy, false);
foreach (PartSummary summary in partOrderedList)
{
Console.WriteLine(summary.Id + ", " + summary.SerialNumber);
}
Console.ReadLine();
}
Now you can pass in the column name as a string and sort.
Hope this helps!
You can also avoid extending and just use a compiled expression tree to accomplish this:
public Func<T, object> ResolveToProperty<T>(String propertyName)
{
Type t = typeof(T);
var paramExpression = Expression.Parameter(t, "element");
var propertyExpression = Expression.Property(paramExpression, propertyName);
return Expression.Lambda<Func<T, object>>(propertyExpression, paramExpression).Compile();
}
string sortName = "SerialNumber";
IEnumerable<PartSummary> partList = FunctionToCreateList();
var partOrderedList = partList.OrderBy(ResolveToProperty<PartSummary>(sortName));

Resources