Combine two ArrayList while summing by a common value - android

Having a object that has 3 properties:
Item
String date;
int value1;
int value2;
I have first ArrayList<Item> listA which contains:
2017-01-18, 0, 0
2017-01-17, 0, 0
2017-01-16, 0, 0
2017-01-15, 0, 0
Second ArrayList<Item> listB which contains:
2017-01-18, 7, 3
2017-01-15, 4, 0
I want to combine both lists, into a final one, having the values summed by same date
2017-01-18, 7, 3
2017-01-17, 0, 0
2017-01-16, 0, 0
2017-01-15, 4, 0

Try this:
public static void sumList(List<Item> list1, List<Item> list2){
List<Item> bigger;
List<Item> smaller;
if(list1.size() > list2.size()){
bigger = list1;
smaller = list2;
} else{
bigger = list2;
smaller = list1;
}
for(int i = 0; i < bigger.size(); i++){
for(int j = 0; j < smaller.size(); j++){
if(bigger.get(i).date.equals(smaller.get(j).date)){
bigger.get(i).value1 = bigger.get(i).value1 + smaller.get(j).value1
bigger.get(i).value2 = bigger.get(i).value2 + smaller.get(j).value2
}
}
}
}
happy coding!

try this
List<Item> firstList = new ArrayList<Item>();
List<Item> secondList = new ArrayList<Item>();
HashMap<String, Item> hashMap = new HashMap<String, Item>();
for(Item item: firstList) {
hashMap.put(item.date, item);
}
for(Item item: secondList) {
Item tempItem = hashMap.get(item.date);
if(tempItem != null) {
tempItem.add(item);
hashMap.put(tempItem.date, tempItem);
} else {
hashMap.put(item.date, item);
}
}
and your item class be like
class Item {
String date;
int value1;
int value2;
public void add(Item item) {
this.value1 = this.value1 + item.value1;
this.value2 = this.value2 + item.value2;
}
}

Related

Listview not updating based on value on Array Adapter

I call the method below to update my listview
ListView list = (ListView) listView.findViewById(R.id.plan_list);
itemsList = sortAndAddSections(getItems_search(name));
ListAdapter adapter = new ListAdapter(getActivity(), itemsList);
list.setAdapter(adapter);
but that code is associated with a value that changes and also this is the other code
private ArrayList<plan_model> getItems_search(String param_cusname) {
Cursor data = myDb.get_search_plan(pattern_email, param_name);
int i = 0;
while (data.moveToNext()) {
String date = data.getString(3);
String remarks = data.getString(4);
items.add(new plan_model(cusname, remarks);
}
return items;
}
and this is my sorter
private ArrayList sortAndAddSections(ArrayList<plan_model> itemList) {
Collections.sort(itemList);
plan_model sectionCell;
tempList.clear();
tmpHeaderPositions.clear();
String header = "";
int addedRow = 0;
int bgColor = R.color.alt_gray;
for (int i = 0; i < itemList.size(); i++) {
String remarks = itemList.get(i).getRemarks();
String date = itemList.get(i).getDate();
if (!(header.equals(itemList.get(i).getDate()))) {
sectionCell = new plan_model(remarks, date);
sectionCell.setToSectionHeader();
tmpHeaderPositions.add(i + addedRow);
addedRow++;
tempList.add(sectionCell);
header = itemList.get(i).getDate();
bgColor = R.color.alt_gray;
}
sectionCell = itemList.get(i);
sectionCell.setBgColor(bgColor);
tempList.add(sectionCell);
if (bgColor == R.color.alt_gray) bgColor = R.color.alt_white;
else bgColor = R.color.alt_gray;
}
tmpHeaderPositions.add(tempList.size());
for (int i = 0; i < tmpHeaderPositions.size() - 1; i++) {
sectionCell = tempList.get(tmpHeaderPositions.get(i));
sectionCell.setDate(sectionCell.getDate() + " (" +
(tmpHeaderPositions.get(i + 1) - tmpHeaderPositions.get(i) - 1) + ")");
}
return tempList;
}
my question is the value name changes but my listview is not how can I update my listview? because i need to update it based on search parameter
If your itemList is being updated properly, you don't need to create another instance of the adapter, just use notifyDataSetChanged():
private void createList() {
ListView list = (ListView) listView.findViewById(R.id.plan_list);
itemsList = sortAndAddSections(getItems_search(name));
adapter = new ListAdapter(getActivity(), itemsList);
list.setAdapter(adapter);
}
private void updateList() {
sortAndAddSections(getItems_search(name)); // Update itemList without re-assign its value, otherwise the adapter will loose reference
adapter.notifyDataSetChanged()
}
In getItems_search() add this line at the beginning:
items.clear();
Every time the value of name changes you have to do the following:
itemsList.clear();
itemsList = sortAndAddSections(getItems_search(name));
list.setAdapter(new ListAdapter(getActivity(), itemsList));

Get list count then update header in listview

I have 2 xml files
Header and Section
then i use some condition to segregate those two and the output of that is this
|8/2/2018|
----------
Data 1
Data 2
|8/2/2018|
----------
Data 1
Data 2
Data 3
It is a listview that groups data with same date and the 1 date header for them.
My question is how can I count each data then update the header? like this
|8/2/2018 (2)|
----------
Data 1
Data 2
|8/2/2018 (3)|
----------
Data 1
Data 2
Data 3
Im using Listview and ListAdapter extends ArrayAdapter
where do i will update?
here
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
ItemModel cell = (ItemModel) getItem(position);
if (cell.isSectionHeader()) {
//Display Date in Header XML
} else {
//Display in Section XML
}
}
or here
private ArrayList sortAndAddSections(ArrayList<ItemModel> itemList) {
ArrayList<ItemModel> tempList = new ArrayList<>();
Collections.sort(itemList);
String header = "";
for (int i = 0; i < itemList.size(); i++) {
if (!(header.equals(itemList.get(i).getDate()))) {
String data = itemList.get(i).getRemarks();
String date = itemList.get(i).getDate()
ItemModel sectionCell = new ItemModel(date,data);
sectionCell.setToSectionHeader();
tempList.add(sectionCell);
header = itemList.get(i).getDate();
}
tempList.add(itemList.get(i));
}
return tempList;
}
Updated
Here is how I transfer the data from database to array
private ArrayList<ItemModel> getItems() {
Cursor data = myDb.get_plan(email);
ArrayList<ItemModel> items = new ArrayList<>();
while (data.moveToNext()) {
String date = data.getString(3);
String data1 = data.getString(4);
items.add(new ItemModel(date,data1));
}
return items;
}
then this where the condition goes
private ArrayList sortAndAddSections(ArrayList<ItemModel> itemList) {
ArrayList<ItemModel> tempList = new ArrayList<>();
String header = "";
for (int i = 0; i < itemList.size(); i++) {
if (!(header.equals(itemList.get(i).getDate()))) {
String date = itemList.get(i).getDate();
String getData1 = itemList.get(i).getData1();
ItemModel sectionCell = new ItemModel(date,data1);
sectionCell.setToSectionHeader();
tempList.add(sectionCell);
header = itemList.get(i).getDate();
}
tempList.add(itemList.get(i));
}
return tempList;
}
this is where i set it in textview
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
ItemModel cell = (ItemModel) getItem(position);
if (cell.isSectionHeader()) {
v = inflater.inflate(R.layout.section_header, null);
v.setClickable(false);
TextView header = (TextView) v.findViewById(R.id.list_date);
header.setText(cell.getDate());
} else {
v = inflater.inflate(R.layout.listview_plan, null);
TextView tv_data1 = v.findViewById(R.id.list_data1);
tv_cusname.setText(cell.getData1());
}
return v;
}
Try this:
private ArrayList sortAndAddSections(ArrayList<ItemModel> itemList) {
ArrayList<ItemModel> tempList = new ArrayList<>();
ArrayList<Integer> tmpHeaderPositions = new ArrayList<>(); // Added
String header = "";
ItemModel sectionCell; // Changed
int addedRow = 0; // Edited
for (int i = 0; i < itemList.size(); i++) {
if (!(header.equals(itemList.get(i).getDate()))) {
String date = itemList.get(i).getDate();
String getData1 = itemList.get(i).getData1();
sectionCell = new ItemModel(date,data1); // Changed
sectionCell.setToSectionHeader();
tmpHeaderPositions.add(i + addedRow); // Edited
addedRow++; // Edited
tempList.add(sectionCell);
header = itemList.get(i).getDate();
}
tempList.add(itemList.get(i));
}
// Added this code block
tmpHeaderPositions.add(tempList.size());
for (int i = 0; i < tmpHeaderPositions.size() - 1; i++) {
sectionCell = tempList.get(tmpHeaderPositions.get(i));
sectionCell.setDate(sectionCell.getDate() + "(" +
(tmpHeaderPositions.get(i + 1) - tmpHeaderPositions.get(i) - 1) + ")");
}
return tempList;
}
Hope that helps!
You can setText later when you get the list of data and then with the help of arraylist.length() you can set the text into section.

Custom Alphabetical sorted listview with sections

I want to make a Custom ListView with sorted alphabetical apps using section Indexer. Since Section Indexer only treat with ArrayList<String> so how do I write custom adapter that have section indexing functionality. Same like this:
Please suggest some solution.
Thats My code
class MyAZAdapter extends ArrayAdapter implements SectionIndexer {
ArrayList myElements;
HashMap azIndexer;
String[] sections;
List apps;
public MyAZAdapter(Context context, int textViewResourceId, List<T> objects, List<ApplicationInfo> apps) {
super(context, textViewResourceId, objects);
myElements = (ArrayList<String>) objects;
azIndexer = new HashMap<String, Integer>(); //stores the positions for the start of each letter
this.apps = apps;
int size = elements.size();
for (int i = size - 1; i >= 0; i--) {
String element = elements.get(i);
//We store the first letter of the word, and its index.
azIndexer.put(element.substring(0, 1), i);
}
Set<String> keys = azIndexer.keySet(); // set of letters
Iterator<String> it = keys.iterator();
ArrayList<String> keyList = new ArrayList<String>();
while (it.hasNext()) {
String key = it.next();
keyList.add(key);
}
Collections.sort(keyList);//sort the keylist
sections = new String[keyList.size()]; // simple conversion to array
keyList.toArray(sections);
}
public int getPositionForSection(int section) {
if (section == 35) {
return 0;
}
for (int i = 0; i < myElements.size(); i++) {
String l = myElements.get(i);
char firstChar = l.toUpperCase().charAt(0);
if (firstChar == section) {
return i;
}
}
return -1;
}
public int getSectionForPosition(int position) {
Log.v("getSectionForPosition", "called");
return 0;
}
public Object[] getSections() {
return sections; // to string will be called to display the letter
}
}class MyAZAdapter<T> extends ArrayAdapter<T> implements SectionIndexer {
ArrayList<String> myElements;
HashMap<String, Integer> azIndexer;
String[] sections;
List<ApplicationInfo> apps;
public MyAZAdapter(Context context, int textViewResourceId, List<T> objects, List<ApplicationInfo> apps) {
super(context, textViewResourceId, objects);
myElements = (ArrayList<String>) objects;
azIndexer = new HashMap<String, Integer>(); //stores the positions for the start of each letter
this.apps = apps;
int size = elements.size();
for (int i = size - 1; i >= 0; i--) {
String element = elements.get(i);
//We store the first letter of the word, and its index.
azIndexer.put(element.substring(0, 1), i);
}
Set<String> keys = azIndexer.keySet(); // set of letters
Iterator<String> it = keys.iterator();
ArrayList<String> keyList = new ArrayList<String>();
while (it.hasNext()) {
String key = it.next();
keyList.add(key);
}
Collections.sort(keyList);//sort the keylist
sections = new String[keyList.size()]; // simple conversion to array
keyList.toArray(sections);
}
public int getPositionForSection(int section) {
if (section == 35) {
return 0;
}
for (int i = 0; i < myElements.size(); i++) {
String l = myElements.get(i);
char firstChar = l.toUpperCase().charAt(0);
if (firstChar == section) {
return i;
}
}
return -1;
}
public int getSectionForPosition(int position) {
Log.v("getSectionForPosition", "called");
return 0;
}
public Object[] getSections() {
return sections; // to string will be called to display the letter
}
}
My AppsActivity code
elements = new ArrayList<String>();
List<ApplicationInfo> apps = getInstalledApplication(getActivity());
for (int i = 0; i < apps.size(); i++) {
elements.add(apps.get(i).loadLabel(getActivity().getPackageManager()).toString());
}
Collections.sort(elements,String.CASE_INSENSITIVE_ORDER); // Must be sorted!
// listview
myListView = (ListView) rootView.findViewById(R.id.myListView);
//myListView.setFastScrollEnabled(true);
MyAZAdapter<String> adapter = new MyAZAdapter<String>(
getActivity(), android.R.layout.simple_list_item_1,
elements, apps);
myListView.setAdapter(adapter);
SideBar indexBar = (SideBar) rootView.findViewById(R.id.sideBar);
indexBar.setListView(myListView);
adapter.sort(new Comparator<String>() {
public int compare(String object1, String object2) {
return object2.compareTo(object1);
};
});
you need the above code right before:
myListView.setAdapter(adapter);

Sorting with Comparator not working

I have to store and manage a volume list in the format:
"100 ml", "200 ml", "300 ml"...
I'm using the SharedPreferences with JSON to store this everytime the list is changed.
I want the list to be ordered, so 100 < 1000, but it is showing like 1000 and 2000 before 300.
Here is my comparator:
mVolumeComparator = new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
int volume1 = Integer.parseInt(s1.replace(" ml", ""));
int volume2 = Integer.parseInt(s2.replace(" ml", ""));
if (volume1 > volume2) {
return 1;
} else if (volume2 > volume1) {
return -1;
} else {
return 0;
}
}
};
And here is my get method:
public static ArrayList<String> getVolumesFromPreference(Context ctx) {
if (!ctx.getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE).contains(KEY_VOLUMES_BUNDLE)) {
startDefaultVolumes(ctx, KEY_VOLUMES_BUNDLE);
}
try {
JSONArray jsonArray = new JSONArray(ctx.getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE).getString(KEY_VOLUMES_BUNDLE, null));
ArrayList<String> lista = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
lista.add(jsonArray.getString(i));
}
Collections.sort(lista, mVolumeComparator);
return lista;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
private static void startDefaultVolumes(Context ctx, String key_bundle) {
JSONArray jsonArray = new JSONArray();
jsonArray.put("269 ml");
jsonArray.put("350 ml");
jsonArray.put("473 ml");
jsonArray.put("550 ml");
jsonArray.put("600 ml");
SharedPreferences.Editor editor = ctx.getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE).edit();
editor.putString(key_bundle, jsonArray.toString());
editor.commit();
}
use Integer.valueOf() method instead Integer.parceInt()
I will recommend you to store only the value "100", "1000", "300" and UNIT if you have more than unit available.
SO, you can order it just with a normal Integer comparator, and then apply the "ml" suffix at runtime
Try this code for sorting arraylist in ascending order.
ArrayList<int> lista = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
lista.add(Integer.parseInt(jsonArray.getString(i)));
}
Collections.sort(lista , new Comparator<Integer >() {
#Override
public int compare(Integer lhs, Integer rhs) {
return Integer.valueOf(lhs).compareTo(Integer.valueOf(rhs));
}
});

Android array error

This is my code:
public ArrayList generare_diferente(){
int rezultat;
ArrayList<String> termeni= new ArrayList<String>();
int termA=parseInt(String.valueOf(randomBetween(1, 20)));
int termB=parseInt(String.valueOf(randomBetween(1, 20)));
if(termA<termB){
int aux; aux=termA; termA=termB; termB=aux;
rezultat=termA-termB;
String diff = termA + "-" + termB;
termeni.add(String.valueOf(rezultat));
termeni.add(diff);
Log.v("termeeeeni", String.valueOf(termeni));
}
return termeni;
}
public void generare_3_diferente() {
ArrayList<String> scaderea1 = new ArrayList<String>();
ArrayList<String> scaderea2 = new ArrayList<String>();
ArrayList<String> scaderea3 = new ArrayList<String>();
int raspuns_corect;
int[] raspunsuri = new int[]{0, 0, 0, 0};
int i = 0;
do {
scaderea1 = generare_diferente();
scaderea2 = generare_diferente();
scaderea3 = generare_diferente();
Button scadere1 = (Button) findViewById(R.id.scadere1);
Button scadere2 = (Button) findViewById(R.id.scadere2);
Button scadere3 = (Button) findViewById(R.id.scadere3);
scadere1.setText((CharSequence) scaderea1.get(1));
scadere2.setText((CharSequence) scaderea2.get(1));
scadere3.setText((CharSequence) scaderea3.get(1));
}
while (scaderea1.get(0) == scaderea2.get(0) || scaderea2.get(0) == scaderea3.get(0) || scaderea3.get(0) == scaderea1.get(0));
raspunsuri[1]= Integer.parseInt(scaderea1.get(0));
raspunsuri[2]= Integer.parseInt(scaderea2.get(0));
raspunsuri[3]= Integer.parseInt(scaderea3.get(0));
pozitia_corecta = parseInt(String.valueOf(randomBetween(1, 3)));
raspuns_corect = raspunsuri[pozitia_corecta];
TextView rezultat = (TextView) findViewById(R.id.Rezultat);
rezultat.setText(raspuns_corect);
}
I'm getting this error:
java.lang.RuntimeException: Unable to start activity : java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
Caused by: java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at java.util.ArrayList.get(ArrayList.java:308)
at com.example.pinguin.MyActivity.generare_3_diferente(MyActivity.java:93)
at .onCreate(MyActivity.java:24)
I don't understand why, the array should not have the size 0.
thank you!
your code seems wrong. because in generare_diferente() if termA<termB or equal you return empty array and then in generare_3_diferente() you try to read data from empty list.
first you should handle this issue.then I think your random number are not generate so termA and termB both is zero or anything and if statement are not true.
change code like this
public ArrayList generare_diferente(){
int rezultat;
ArrayList<String> termeni= new ArrayList<String>();
int termA=random.nextInt(max - min + 1) + min ;
int termB=random.nextInt(max - min + 1) + min ;
if(termA<termB){
int aux; aux=termA; termA=termB; termB=aux;
rezultat=termA-termB;
String diff = termA + "-" + termB;
termeni.add(String.valueOf(rezultat));
termeni.add(diff);
Log.v("termeeeeni", String.valueOf(termeni));
}
return termeni.clone();
}
public void generare_3_diferente() {
ArrayList<String> scaderea1 = new ArrayList<String>();
ArrayList<String> scaderea2 = new ArrayList<String>();
ArrayList<String> scaderea3 = new ArrayList<String>();
int raspuns_corect;
int[] raspunsuri = new int[]{0, 0, 0, 0};
int i = 0;
do {
scaderea1 = generare_diferente();
scaderea2 = generare_diferente();
scaderea3 = generare_diferente();
Button scadere1 = (Button) findViewById(R.id.scadere1);
Button scadere2 = (Button) findViewById(R.id.scadere2);
Button scadere3 = (Button) findViewById(R.id.scadere3);
if(scaderea1.size()>0 && scaderea2.size()>0 && scaderea3.size()>0){
scadere1.setText((CharSequence) scaderea1.get(1));
scadere2.setText((CharSequence) scaderea2.get(1));
scadere3.setText((CharSequence) scaderea3.get(1));
}else{
scadere1.setText("something");
scadere2.setText("something");
scadere3.setText("something");
break;
}
}
while (scaderea1.get(0) == scaderea2.get(0) || scaderea2.get(0) == scaderea3.get(0) || scaderea3.get(0) == scaderea1.get(0));
if(scaderea1.size()>0 && scaderea2.size()>0 && scaderea3.size()>0){
raspunsuri[1]= Integer.parseInt(scaderea1.get(0));
raspunsuri[2]= Integer.parseInt(scaderea2.get(0));
raspunsuri[3]= Integer.parseInt(scaderea3.get(0));
}else{
raspunsuri[1]= Integer.parseInt("0");
raspunsuri[2]= Integer.parseInt("0");
raspunsuri[3]= Integer.parseInt("0");
}
pozitia_corecta = parseInt(String.valueOf(randomBetween(1, 3)));
raspuns_corect = raspunsuri[pozitia_corecta];
TextView rezultat = (TextView) findViewById(R.id.Rezultat);
rezultat.setText(raspuns_corect);
}

Categories

Resources