How to arrange array of objects with same property value? - algorithm

I have an person model with two property like this:
int id;
String name;
and some object with this data:
person0 = {1,"James"};
person1 = {2,"James"};
person2 = {3,"James"};
person3 = {4,"Barbara"};
person4 = {5,"Barbara"};
person5 = {6,"Ramses"};
and array contain objects:
firstArray = [person0, person1, person2, person3, person4, person5];
Therefore how can have this array:
secondArray = [
[person0, person1, person2],
[person3, person4],
[person5]
]
Thank you.

If language does not matter.
map = new Map();
for (persona of personas) {
name = persona.name;
arrayForName = map.get(name);
if (arrayForName == null) {
arrayForName = [];
map.put(name, arrayForName);
}
arrayForName.put(persona)
}
The idea is to have a map (which is a collection key->value).
The value of the map should in turn be an array.
To add elements efficiently, you iterate only once through the data, and add arrays each time a new key is discovered (i.e. the name).
In Java it would be something like:
Map<String, List<Persona>> map = new HashMap<>();
for (Persona persona : personas) {
String name = persona.getName();
List<Persona> listForName = map.get(name);
if (listForName == null) {
listForName = new ArrayList<Persona>();
map.put(name, listForName);
}
listForName.add(persona)
}

Try this code in Java Android:
ArrayList<ArrayList<Person>> secondArr = new ArrayList<>();
ArrayList<Course> tempArr = new ArrayList<>();
for (int i = 0; i < firstArr.size(); i++) {
if ((i + 1) >= firstArr.size()) {
tempArr.add(firstArr.get(i));
secondArr.add(tempArr);
} else {
if (firstArr.get(i).name .equals( firstArr.get(i + 1).name) ) {
tempArr.add(firstArr.get(i));
} else {
tempArr.add(firstArr.get(i));
secondArr.add(tempArr);
tempArr = new ArrayList<>();
}
}
}
Finally secondArr prepared.
And if list not sorted we can use code like this:
for (int i = 0; i <firstArr.size() ; i++) {
boolean isAdd = false;
for (int j = 0; j < secondArr.size() ; j++) {
if (secondArr.get(j).get(0).getName().equals(firstArr.get(i).getName())){
secondArr.get(j).add(firstArr.get(i));
isAdd =true;
break;
}
}
if (!isAdd){
ArrayList<Person> arrayList = new ArrayList<>();
arrayList.add(firstArr.get(i));
secondArr.add(arrayList);
}
}

Related

I want to Group questions and answers LINQ and have them display properly

I'm trying to group properly to have my cell distribute eveningly. The printout is coming very odd and uneven.
is it the table i'm creating or group or both? I think the group is correct. My results are as shown in the image below.
Gold is the heading,
Green are the questions,
Red are the answers
Mt table is is below
var Sections = new OncologySection().SelectSections(projectID.ToString());
int iSection = 0;
int igroups = 0;
int ianswer = 0;
tb.CssClass = "";
tb.BorderWidth = 1;
tb.Width = new Unit("780px");
tb.Attributes.Add("runat", "server");
foreach (OncologySection section in Sections)
{
TableRow row1 = new TableRow();
iSection++;
// var getDistinctQuestion = getVoterAnswerstoList.Select(s => s.QuestionText ,s.Id).Distinct().ToList();
var getVoterAnswerstoList = new OncologyGeneratePDFDAL().DataforPDFCreation(Convert.ToInt32(projectID), Convert.ToInt32(voterid), Convert.ToInt32(caseId), Convert.ToInt32(voteSurveyId), Convert.ToInt32(section.SectionID)).OrderBy(os => os.SortOrder);
//var groupedCustomerList = getVoterAnswerstoList
// .GroupBy(u => u.QuestionText, u.QuestionText)
// .Select(grp => grp.ToList())
// .ToList();
var groupedCustomerList = getVoterAnswerstoList.GroupBy(x => new { x.QuestionText, x.DynamicValue }).ToList();
TableCell cell1 = new TableCell();
cell1.BorderWidth = 1;
cell1.Text = section.SectionName;
cell1.BorderColor = System.Drawing.Color.Goldenrod;
cell1.ColumnSpan = groupedCustomerList.Count();
row1.Cells.Add(cell1);
tb.Rows.Add(row1);
TableRow row2 = new TableRow();
foreach (var groups in groupedCustomerList)
{
igroups++;
TableCell cell2 = new TableCell();
var q = (from s in groups select s.QuestionText).FirstOrDefault();
cell2.BorderWidth = 1;
cell2.Text = q;
cell2.BorderColor = System.Drawing.Color.Green;
cell2.ColumnSpan = groupedCustomerList.Count();
row2.Cells.Add(cell2);
if (igroups == groupedCustomerList.Count())
{
tb.Rows.Add(row2);
}
else
{
row2.Cells.Add(cell2);
}
TableRow row3 = new TableRow();
foreach (var answers in groups)
{
ianswer++;
TableCell cell3 = new TableCell();
cell3.BorderWidth = 1;
cell3.BorderColor = System.Drawing.Color.DarkRed;
if (answers.DataTypeId == 7)
{
cell3.Text = answers.DynamicValue.ToString();
}
else if ((answers.DataTypeId == 5) || (answers.DataTypeId == 6) || (answers.DataTypeId == 8))
{
if (answers.VotingValue != 0)
{
cell3.Text = answers.VotingValue.ToString();
}
else
{
cell3.Text = " ";
}
}
else
{
cell3.Text = " ";
}
row3.Cells.Add(cell3);
tb.Rows.Add(row3);
}
}
}
}

Iterate lists of different length using Java 8 streams

I am trying to iterate over three lists of different size but not getting the exact logic of how i can retrieve data from them and store in another list.
I was able to handle up to two list until I add some more filtration to the elements. For now I am using 3 for loops but i want to use Java 8 streams if possible. Can someone please suggest me the correct logic for the below iterations.
public class CustomDto {
public static void main(String... args) {
List<String> list1 = Arrays.asList("Hello", "World!");
List<String> list2 = Arrays.asList("Hi", "there");
List<String> list3 = Arrays.asList("Help Me");
Map<Integer, Object> map = new HashMap<>();
for (int i = 0; i < list1.size(); i++) {
List<String> list4 = new LinkedList();
for (int j = 0; j < list2.size(); j++) {
for (int k = 0; k < list3.size(); k++) {
if (!(list2.get(j).equals(list3.get(k))))
list4.add(list2.get(j));
}
if (j > list4.size() - 1) {
list4.add(null);
}
}
map.put(i, list4);
}
}
}
All i want to convert the above code into stream, in which i can iterate a list inside another list and can use the index of one another.
public static void main(String... args) {
List<String> list1 = Arrays.asList("Hello", "World!");
List<String> list2 = Arrays.asList("Hi", "there");
List<String> list3 = Arrays.asList("Help Me");
List<String> list4 = concat(list1, list2, list3); //you can add as many lists as you like here
System.out.println(list4);
}
private static List<String> concat(List<String>... lists) {
return Stream.of(lists)
.flatMap(List::stream)
.collect(Collectors.toList());
}
Output
[Hello, World!, Hi, there, Help Me]
Try this create a multiple dimension array out of List, from there you can use stream too
Customdto[][] listArray = new Customdto[][]{ l1.toArray(new Customdto[]{})
, l2.toArray(new Customdto[]{}), l3.toArray(new Customdto[]{})};
int size = listArray[0].length > listArray[1].length && listArray[0].length > listArray[2].length ?listArray[0].length
:(listArray[1].length > listArray[2].length ? listArray[1].length:listArray[2].length);
for(int i = 0; i <size;i++)
{
if(listArray[0].length >i && listArray[1].length >i && listArray[2].length >i &&
listArray[0][i].equals(listArray[1][i])
&& listArray[1][i].getCalendarDate().equals(listArray[2][i].getCalendarDate()))
{
l4.add(listArray[1][i]);
}else
{
l4.add(null);
}
}
Tried with Below Input
List<Customdto> l1 = new ArrayList<Customdto>();
List<Customdto> l2 = new ArrayList<Customdto>();
List<Customdto> l3 = new ArrayList<Customdto>();
List<Customdto> l4 = new ArrayList<Customdto>();
l1.add(new Customdto(1));
l1.add(new Customdto(2));
l1.add(new Customdto(3));
l1.add(new Customdto(4));
l2.add(new Customdto(1));
l2.add(new Customdto(2));
l2.add(new Customdto(3));
l3.add(new Customdto(1));
l3.add(new Customdto(2));
Output is
[Customdto [id=1], Customdto [id=2], null, null]

top "N" rows in each group using hibernate criteria

Top / Bottom / Random "N" rows in each group using Hibernate Criteria / Projections
How to retrieve top 5 Questions for Each Sub Topic
DetachedCriteria criteria = DetachedCriteria.forClass(Question.class);
ProjectionList projList = Projections.projectionList();
projList.add(Projections.property("questionId"));
projList.add(Projections.groupProperty("subTopicId"));
criteria.setProjection(projList);
List<Object> resultList = (List<Object>) getHibernateTemplate().findByCriteria(criteria);
Iterator<Object> itr = resultList.iterator();
List<Integer> questionIdList = new ArrayList<Integer>();
while(itr.hasNext()){
Object ob[] = (Object[])itr.next();
System.out.println(ob[0]+" -- "+ob[1]);
}
I am Using the Code Below for Getting Result Temporally, Is there any solution from Hibernate using Criteria API / Any other alternate way to get the result
Set<Integer> getQuestionsBySubTopicWithLimit(Set<Integer> questionIdsSet, Integer subjectId, Integer limit, Integer status) {
DetachedCriteria criteria = DetachedCriteria.forClass(Question.class);
if(subjectId!=null && subjectId!=0){
criteria.add(Restrictions.eq("subjectId", subjectId));
}
if(status!=null){
criteria.add(Restrictions.eq("status", status));
}
if(questionIdsSet!=null && !questionIdsSet.isEmpty()){
criteria.add(Restrictions.not(Restrictions.in("questionId", questionIdsSet)));
}
ProjectionList projList = Projections.projectionList();
projList.add(Projections.property("questionId"));
projList.add(Projections.property("subTopicId"));
criteria.add(Restrictions.sqlRestriction("1=1 order by sub_topic_id, rand()"));
criteria.setProjection(projList);
List<Object> resultList = (List<Object>) getHibernateTemplate().findByCriteria(criteria);
Iterator<Object> itr = resultList.iterator();
Set<Integer> tmpQuestionIdsSet = new HashSet<Integer>();
Integer subTopicId = 0, tmpSubTopicId = 0;
Integer count = 0;
while(itr.hasNext()){
Object ob[] = (Object[])itr.next();
if(count==0){
subTopicId = (Integer) ob[1];
}
tmpSubTopicId = (Integer) ob[1];
if(tmpSubTopicId!=subTopicId){
subTopicId = tmpSubTopicId;
count = 0;
}
count++;
if(count<=limit){
tmpQuestionIdsSet.add((Integer) ob[0]);
}
}
return tmpQuestionIdsSet;
}

LINQ and removing duplicates from an array of objects

I'm trying to de-dupe an array of objects using two columns where the second column is a Dictionary. Best way to describe this is to show some code:
class MyClass
{
public int ID;
public Dictionary<int, int> Dict = new Dictionary<int, int>();
}
And now to create some objects:
List<MyClass> list = new List<MyClass>();
MyClass mc1 = new MyClass();
list.Add(mc1); mc1.ID = 1; mc1.Dict.Add(1, 1);
MyClass mc2 = new MyClass();
list.Add(mc2); mc2.ID = 1; mc2.Dict.Add(1, 1);
MyClass mc3 = new MyClass();
list.Add(mc3); mc3.ID = 1; mc3.Dict.Add(1, 2);
MyClass mc4 = new MyClass();
list.Add(mc4); mc4.ID = 2; mc4.Dict.Add(1, 1);
What I'm looking to accomplish is to distinct by ID and Dict. The results should look like this:
List of MyClass objects (not pretty)
1 //MyClass.ID
1,1 //MyClass.Dictionary
1
1,2
2
1,1
Notice that one of the objects was dropped from the original list because it had a duplicate ID and Dict (dictionary values). I've been playing around with alternate versions of:
var s = from p in list
group p by p.ID into group1
from group2 in
(from p in group1 group p by p.Dict)
group group2 by group1.Key;
but just haven't had any luck. Appreciate any insight folks might have on solving this problem.
PS - I'm not changing the rules but I believe a GROUP BY and a SELECTFIRST will be cleaner than a DISTINCT with its extra code for a Comparer. A pat on the back for anyone who can figure this out using GROUP BY.
For reference types you should add equality comparer in order to do what you want. Add the following class:
public class MyClassComparer : IEqualityComparer<MyClass>
{
public bool Equals(MyClass left, MyClass right)
{
if (left == null && right == null)
{
return true;
}
if (left == null || right == null)
{
return false;
}
if (left.ID == right.ID)
{
if (left.Dict == null && right.Dict == null)
{
return true;
}
if (left.Dict == null || right.Dict == null)
{
return false;
}
if (left.Dict.Count != right.Dict.Count)
{
return false;
}
foreach(var key in left.Dict.Keys)
{
if(!right.Dict.ContainsKey(key))
return false;
if (left.Dict[key] != right.Dict[key])
return false;
}
return true;
}
else return false;
}
public int GetHashCode(MyClass author)
{
return (author.ID).GetHashCode();
}
}
And use that comparer in Distinct override:
List<MyClass> list = new List<MyClass>();
MyClass mc1 = new MyClass();
list.Add(mc1); mc1.ID = 1; mc1.Dict.Add(1, 1);
MyClass mc2 = new MyClass();
list.Add(mc2); mc2.ID = 1; mc2.Dict.Add(1, 1);
MyClass mc3 = new MyClass();
list.Add(mc3); mc3.ID = 1; mc3.Dict.Add(1, 2);
MyClass mc4 = new MyClass();
list.Add(mc4); mc4.ID = 2; mc4.Dict.Add(1, 1);
var result = list.Distinct(new MyClassComparer()).ToList();
You should improve GetHashCode method. It will be your homework :)
Can I have half a pat for the following ? :)
var filteredList = list.GroupBy(mc => mc.ID)
.SelectMany(gr => gr.Distinct(new MyClassComparer()))
.ToList();
Comparer:
public class MyClassComparer : IEqualityComparer<MyClass>
{
public bool Equals(MyClass a, MyClass b)
{
return a.Dict.Count == b.Dict.Count && !a.Dict.Except(b.Dict).Any();
}
public int GetHashCode(MyClass a)
{
return a.ID;
}
}

split one big datatable to two separated datatables

I´m exporting datatables to Excel workbook. Problem is that the datatable holds 90000 rows and excel can only hold 67000 rows in every sheet.
So..
How can i divide one big datatable to two datatables, maybe with Linq ?
Then i can have datatable1 in sheet1 and datatable2 in sheet2
Sincerly
agh
Assuming that you're getting the 90,000 rows for this DataTable from a database somewhere, the most efficient approach would be to modify your SELECT statement into two new SELECT statements, each of which returns < 67,000 rows, and then do everything else the same.
Split your recordset. Perform one SELECT that extracts all 90,000 rows, and split it on Excel import step.
private List<DataTable> CloneTable(DataTable tableToClone, int countLimit)//Split function
{
List<DataTable> tables = new List<DataTable>();
int count = 0;
DataTable copyTable = null;
foreach (DataRow dr in tableToClone.Rows)
{
if ((count++ % countLimit) == 0)
{
copyTable = new DataTable();
copyTable = tableToClone.Clone();
copyTable.TableName = "Sample" + count;
tables.Add(copyTable);
}
copyTable.ImportRow(dr);
}
return tables;
}
protected void LinkReport_Click(object sender, EventArgs e)
{
DataTable dt2 = (DataTable)ViewState["dtab"];
List<DataTable> dt1 = CloneTable(dt2, 5);
DataSet ds = new DataSet("dst");
for (int i = 0; i < dt1.Count; i++)
{
ds.Tables.Add(dt1[i]);
}
string filePath = Server.MapPath("Reports/").ToString() + "master.xls";
FileInfo file = new FileInfo(filePath);
if (file.Exists)
{
file.Delete();
}
Export(ds, filePath);// Export into Excel
}
Clone - The fastest method to create tables with original columns structure is Clone method.
Export into Excel
private void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
obj = null;
}
finally
{
GC.Collect();
}
}
public void Export(DataSet ds, string filePath)
{
string data = null;
string columnName = null;
int i = 0;
int j = 0;
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
//Excel.Worksheet xlWorkSheet;
Excel.Worksheet xlWorkSheet = null;
object misValue = System.Reflection.Missing.Value;
Excel.Range range;
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Add(misValue);
//xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
for (int l = 0; l < ds.Tables.Count; l++)
{
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(l + 1);
xlWorkSheet.Cells[1, 1] = "Report";
xlWorkSheet.get_Range("A1:D1", Type.Missing).Merge(Type.Missing);
xlWorkSheet.get_Range("A1", "D1").Font.Bold = true;
xlWorkSheet.Cells.Font.Name = "Courier New";
if (l == 0)
{
xlWorkSheet.Name = "Sheet1";
}
else if (l == 1)
{
xlWorkSheet.Name = "Sheet2";
}
else if (l == 2)
{
xlWorkSheet.Name = "Sheet3";
}
else if (l == 3)
{
xlWorkSheet.Name = "Sheet4";
}
else if (l == 4)
{
xlWorkSheet.Name = "Sheet5";
}
for (i = 0; i <= ds.Tables[l].Rows.Count - 1; i++)
{
for (j = 0; j <= ds.Tables[l].Columns.Count - 1; j++)
{
columnName = ds.Tables[l].Columns[j].ColumnName.ToString();
xlWorkSheet.Cells[3, j + 1] = columnName;
data = ds.Tables[l].Rows[i].ItemArray[j].ToString();
xlWorkSheet.Cells[i + 5, j + 1] = data;
}
}
}
//for (i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
//{
// for (j = 0; j <= ds.Tables[0].Columns.Count - 1; j++)
// {
// data = ds.Tables[0].Rows[i].ItemArray[j].ToString();
// xlWorkSheet1.Cells[i + 1, j + 1] = data;
// }
//}
xlWorkBook.SaveAs(filePath, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
// kill all excel processes
Process[] pros = Process.GetProcesses();
for (int p = 0; p < pros.Length; p++)
{
if (pros[p].ProcessName.ToLower().Contains("excel"))
{
pros[p].Kill();
break;
}
}
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
}
Try this One.. I have Worked out in Visual Studio 2005
DataTable[] splittedtables = dt.AsEnumerable()
.Select((row, index) => new { row, index })
.GroupBy(x => x.index / Input From User) // integer division, the fractional part is truncated
.Select(g => g.Select(x => x.row).CopyToDataTable())
.ToArray();
This should work.

Resources