Sort ListView Items - android

I have 2 item types in my listview, Venue and Distance.
List<String> ls_Distance;
List<String> ls_Venue;
ls_Distance = new ArrayList<String>();
ls_Venue = new ArrayList<String>();
I'm adding string items into both list arrays in a for loop.
(I'm assuming sort function can sort a list of numbers that are in string format e.g. "9","15","20" etc.. and I don't need to covert to int first?)
ls_Distance.add(data_Distance);
ls_Venue.add(data_Venue);
I would like to sort the items by distance (showing lowest distance first), and maintain the index of the venue.
Note: This sorting can only be done once data is added to array and not before (distance obtained from location updates calculations)
Then I want to set my listview adpater after sorting:
ListViewRowCount = ls_Venue.size();
lv.setAdapter(lv_custom_adapter);
EDIT:
My code for sorting (not working)
private void sortByDistance() {
Collections.sort(ls_Distance, new Comparator<String>() {
#Override
public int compare(String lhs, String rhs) {
Log.v("TAG", "zzz_compare_lhs: " +lhs);
Log.v("TAG", "zzz_compare_rhs: " +rhs);
return lhs.compareTo(rhs);
}
});
//setAdapter();
}

Resolved: (Using TreeMap)
private void consolidateData() {
if (currentLat != 0.0){
Map<Integer, String> map = new TreeMap<Integer, String>();
for (int i=0;i<stringArr_markerVenue.size();i++){
data_Distance = Integer.parseInt(stringArr_markerDistance.get(i));
data_Venue = stringArr_markerVenue.get(i);
//ls_Distance.add(data_Distance);
//ls_Venue.add(data_Venue);
map.put(data_Distance, data_Venue);
}
TreeMap<Integer, String> sorted = new TreeMap<>(map);
Set<Map.Entry<Integer, String>> mappings = sorted.entrySet();
System.out.println("HashMap after sorting by keys in ascending order ");
for(Map.Entry<Integer, String> mapping : mappings){
System.out.println(mapping.getKey() + " ==> " + mapping.getValue());
int data_Distance = mapping.getKey();
String data_Venue = mapping.getValue();
Log.v("TAG", "zzz_com: " + data_Distance + " ==> " + data_Venue);
ls_Distance.add(data_Distance+"");
ls_Venue.add(data_Venue);
}
setAdapter();
}
}
private void setAdapter() {
ListViewRowCount = ls_Distance.size();
lv.setAdapter(lv_custom_adapter);
}

Related

Get the sum of integers inside an ArrayList under same String name using Map

I have an ArrayList with one String value and two Integer values. I want the sum of integers under the same String value. For example
aaa , 1 , 2
aaa , 2 , 1
bbb , 1 , 2
ccc , 3 , 3
ccc , 1 , 2
ccc , 2 , 2
So final list should come as
aaa , 3, 3
bbb , 1, 2
ccc , 6, 7
I was able to get the sum using one String and one Integer.
this is what i used for one String and one Integer.
ArrayList<InvoiceData> invoiceHeaderList = new ArrayList<>();
invoiceHeaderList.clear();
Map<String, Integer> sumMap = new TreeMap<String, Integer>();
for (ItemData dashboardOneData : invoiceList) {
String key = dashboardOneData.getInvoiceNo() + "#" + dashboardOneData.getInvoiceDate();
if (sumMap.containsKey(key)) {
int sum = sumMap.get(key);
sum += dashboardOneData.getMatQty();
sumMap.put(key, sum);
} else {
sumMap.put(key, dashboardOneData.getMatQty());
}
}
for (Map.Entry<String, Integer> e : sumMap.entrySet()) {
String[] splitInvoice;
InvoiceData invTempData = new InvoiceData();
if (e.getKey() != null || !e.getKey().equals("")) {
splitInvoice = e.getKey().split("#+");
invTempData.setInvoiceNo(splitInvoice[0]);
invTempData.setInvoiceDate(splitInvoice[1]);
invTempData.setInvoiceQty(e.getValue());
invoiceHeaderList.add(invTempData);
}
}
I tried to do as below but no luck, I was not able to take the sum of the two integers inside the method.
public class QuantityData {
private int oriQty;
private int newQty;
public QuantityData() {
}
}
Method....
ArrayList<InvoiceData> invoiceHeaderList = new ArrayList<>();
invoiceHeaderList.clear();
Map<String, List<QuantityData>> sumMap = new TreeMap<String, List<QuantityData>>();
for (ItemData dashboardOneData : invoiceList) {
String key = dashboardOneData.getInvoiceNo() + "#" + dashboardOneData.getInvoiceDate();
QuantityData qtyData = new QuantityData();
if (sumMap.containsKey(key)) {
ArrayList<QuantityData> qtyArrayList = new ArrayList<>();
qtyArrayList.add(qtyData);
sumMap.put(key, qtyArrayList);
} else {
ArrayList<QuantityData> qtyArrayList = new ArrayList<>();
qtyData.setOriQty(dashboardOneData.getMatQty());
qtyData.setNewQty(dashboardOneData.getNewMatQty());
qtyArrayList.add(qtyData);
sumMap.put(key, qtyArrayList);
}
}
for (Map.Entry<String, List<QuantityData>> e : sumMap.entrySet()) {
String[] splitInvoice;
InvoiceData invTempData = new InvoiceData();
if (e.getKey() != null || !e.getKey().equals("")) {
}
}
If I understood your goal correctly, you don't need ArrayLists at all.
Have you tried something like this?
Map<String, QuantityData> sumMap = new TreeMap<String, QuantityData>();
QuantityData qtyData;
for (ItemData dashboardOneData : invoiceList) {
String key = dashboardOneData.getInvoiceNo() + "#" + dashboardOneData.getInvoiceDate();
if (sumMap.containsKey(key)) {
qtyData = sumMap.get(key)
qtyData.setOriQty(qtyData.getOriQty() + dashboardOneData.getMatQty());
qtyData.setNewQty(qtyData.getNewQty() + dashboardOneData.getNewQty());
} else {
qtyData = new QuantityData();
qtyData.setOriQty(dashboardOneData.getMatQty());
qtyData.setNewQty(dashboardOneData.getNewMatQty());
}
sumMap.put(key, qtyData);
}
I don't entirely understand what your input data structure looks like, but I'll do my best.
Let's say you have an input data structure that looks something like this:
#Data //using Lombok #Data annotation
class Data{
String key;
Integer[] values;
}
then you can do something like this:
Map<String, Integer[]> getSummedDataByKey(List<Data> items){
Map<String, Integer[]> summedData;
for (Data d : items){
if (!summedData.contains(d.getKey())){
summedData.put(d.getKey(), d.getValues());
}else{
Integer[] oldValues = summedData.get(d.getKey());
for (int i = 0; i < oldValues.length; i++){
oldValues[i] += d.getValues()[i];
}
summedData.put(d.getKey(), oldvalues);
}
}
return summedData;
}
this is what I figured out.
for (ItemData dashboardOneData : invoiceList) {
String key = dashboardOneData.getInvoiceNo() + "#" + dashboardOneData.getInvoiceDate();
QuantityData qtyData = new QuantityData();
if (sumMap.containsKey(key)) {
ArrayList<QuantityData> qtyArrayList = new ArrayList<>();
List<QuantityData> bobs = sumMap.get(key);
int sum1 = bobs.get(0).getOriQty();
int sum2 = bobs.get(0).getNewQty();
sum1 += dashboardOneData.getMatQty();
sum2 += dashboardOneData.getNewMatQty();
qtyData.setOriQty(sum1);
qtyData.setNewQty(sum2);
qtyArrayList.add(qtyData);
sumMap.put(key, qtyArrayList);
} else {
ArrayList<QuantityData> qtyArrayList = new ArrayList<>();
qtyData.setOriQty(dashboardOneData.getMatQty());
qtyData.setNewQty(dashboardOneData.getNewMatQty());
qtyArrayList.add(qtyData);
sumMap.put(key, qtyArrayList);
}
}

How to get Hashmap Data

I had seen many examples regarding Hashmap Data but I am not getting the data as required.
Here is my code:
HashMap<String,ArrayList<String>> citylist = new HashMap<String, ArrayList<String>>();
ArrayList<String> Gujarat = new ArrayList<String>();
Gujarat.add("Surat");
Gujarat.add("Baroda");
Gujarat.add("Ahmedabad");
ArrayList<String> Rajasthan = new ArrayList<String>();
Rajasthan.add("Udaipur");
Rajasthan.add("Jaipur");
ArrayList<String> UP= new ArrayList<String>();
UP.add("Lucknow");
UP.add("Agra");
citylist.put("Gujarat", Gujarat);
citylist.put("UP", UP);
citylist.put("Rajasthan", Rajasthan);
It is in recyclerview how to get this type of data in BindViewHolder?
Toast is coming like:
{Rajasthan=[Udaipur, Jaipur], UP=[Lucknow, Agra], Gujarat=[Surat, Baroda, Ahmedabad]}
I had used this method to get but error is coming:
public void onBindViewHolder(MyViewHolder holder, int position) {
ArrayList<String> lst = citylist.get("" + position);
for (Integer i = 0; i < lst.size(); i++) {
holder.tv.setText(citylist.toString());
Log.e("Hashmap....", ""+holder.tv );
}
the output should be like Gujarat is state and surat baroda and ahmedabad are cities?
First create one ArrayList with all state :
ArrayList<String> stateList = new ArrayList<String>();
stateList.add("Gujarat");
stateList.add("UP");
stateList.add("Rajasthan");
Second create one HashMap with each state name as Key and each state city as Value:
HashMap<String,ArrayList<String>> stateCityMap = new HashMap<String,ArrayList<String>>()
ArrayList<String> gujaratCityList = new ArrayList<String>();
gujaratCityList.add("Ahmedabad");
gujaratCityList.add("Surat");
gujaratCityList.add("Baroda");
.......................
ArrayList<String> upCityList = new ArrayList<String>();
upCityList.add("Lucknow");
upCityList.add("Agra");
..........................
ArrayList<String> rajasthanCityList = new ArrayList<String>();
rajasthanCityList.add("Udaipur");
rajasthanCityList.add("Jaipur");
...........................
stateCityMap.put("Gujarat",gujaratCityList);
stateCityMap.put("UP",upCityList);
stateCityMap.put("Rajasthan",rajasthanCityList);
Now get all city name based on state in Adapter :
public void onBindViewHolder(MyViewHolder holder, int position) {
Log.e("State : ",stateList.get(position));
ArrayList<String> cityList= (ArrayList<String>)stateCityMap.get(stateList.get(position));
for(String cityName : cityList){
Log.e("City : ",cityName);
}
}
you can get like below.
Iterator iterator = map.keySet().iterator();
while(iterator.hasNext()) {
String key=(String)iterator.next();
String value=(String)map.get(key);
Toast.makeText(ctx, "Key: "+key+" Value: "+value, Toast.LENGTH_LONG).show();
}
HashMaps do not preserve ordering:
This class makes no guarantees as to the order of the map; in
particular, it does not guarantee that the order will remain constant
over time.
Take a look at LinkedHashMap, which guarantees a predictable iteration order.
You might wanna try something like this.
for (Map.Entry<String, ArrayList<String>> entry : citylist.entrySet())
{
String key = entry.getKey(); // Your State
String value = entry.getValue(); // Your List of Cities.
// Split data and insert in Views
}
However I recommend (for easy to use case) keep a List of all the states and get Value from HashMap using keys from this List of states.
Please check it :
ArrayList<HashMap<String, String>> arrayList = new ArrayList<HashMap<String,String>>();
HashMap<String, String> h1 = new HashMap<String, String>();
h1.put("h1_key_1", "h1_value_1");
h1.put("h1_key_2", "h1_value_2");
arrayList.add(h1);
for (HashMap<String, String> hashMap : arrayList) {
System.out.println(hashMap.keySet());
for (String key : hashMap.keySet()) {
System.out.println(hashMap.get(key));
}
}
Try This:
public static void printMap(Map mp) {
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
it.remove(); // avoids a ConcurrentModificationException
}
}

Sort two dependent string arrays

I Have two String arrays in my application, One containing Country names, and other containing corresponding extension code, But the issue is that the names of countries are not properly ordered in alphabetical order,
public static final String[] m_Countries = {
"---select---", "Andorra", ...., "Zimbabwe"};
public static final String[] m_Codes = {
"0", "376",...., "263"};
These are the arrays,
So my question is, is there any way to sort the first array such that the second array also changes to corresponding position without writing my own code?
If not, what's the best sort method i can use for these arrays?
Any kind of help will be greatly appreciated.
Form TreeMap from your array and all your data get sort. After that fill your respective array with Key and Values.
TreeMap<String, String> map = new TreeMap<>();
int length = m_Countries.length;
for(int i=0;i<length;i++){
map.put(m_Countries[i], m_Codes[i]);
}
String[] countries = map.keySet().toArray(new String[map.keySet().size()]);
System.out.println("Country:"+Arrays.toString(countries));
String[] codes = map.values().toArray(new String[map.values().size()]);
System.out.println("Codes:"+Arrays.toString(codes));
Result:
Country:[---select---, Afghanistan, ..., Zimbabwe]
Codes:[0, 93,.... , 263]
Method 1.
You can create a hashMap to store the original country to code.
private void handle(String[] m_Countries, String[] m_Codes, Map<String, String> map) {
if (m_Codes == null || m_Countries == null || map == null) {
return;
}
//
final int codeCount = m_Codes.length;
final int countryCount = m_Countries.length;
final int count = Math.min(codeCount, countryCount);
for (int i = 0; i < count; i++) {
map.put(m_Countries[i], m_Codes[i]);
}
// TODO sort
// get code by country name by map.get(country)
}
Method 2.
You can make a List of pairs which contains country and code. Then sort the list.
private List<Pair<String, String>> sortCountryWithCode(String[] m_Countries, String[] m_Codes) {
if (m_Codes == null || m_Countries == null) {
return null;
}
//
final int codeCount = m_Codes.length;
final int countryCount = m_Countries.length;
final int count = Math.min(codeCount, countryCount);
if (count == 0) {
return null;
}
// generate a list
List<Pair<String, String>> list = new ArrayList<>();
for (int i = 0; i < count; i++) {
list.add(new Pair<String, String>(m_Countries[i], m_Codes[i]));
}
// sort
Collections.sort(list, new Comparator<Pair<String, String>>() {
#Override
public int compare(Pair<String, String> lhs, Pair<String, String> rhs) {
return lhs.first.compareToIgnoreCase(rhs.first);
}
});
return list;
}
code with love. :)

How to sort a listview by string numbers?

Here is my main issue, after some researches, I didn't find a solution so... I would like to sort my list of custom objects. These items have a price, but for a reason they are strings not int. I would like to know how to achieve this, thanks for helping !
Little personnal question, sorting a listview and a recyclerview are they done the same way ?
EDIT:
public class Product implements Parcelable {
private String imgUrl, titre, description, prix, nomAgence, pays, ville, type_produit, nbPieces = null;
List<String> urlImageList_thumb = new ArrayList<>();
List<String> urlImageList_full = new ArrayList<>();
private int isAdded = 0;
/* getters and setters*/
}
EDIT 2 :After your help, here's my code for comparable
#Override
public int compareTo(Product otherProduct) {
String tmp = prix.replace(" €", "");
String tmp2 = otherProduct.prix.replace(" €", "");
//Integer p1 = Integer.valueOf(tmp); --> does not work
//Integer p2 = Integer.valueOf(tmp2); --> does not work
Integer p1 = Integer.parseInt(tmp); //same error
Integer p2 = Integer.parseInt(tmp2); // same error
return p1.compareTo(p2);
}
Here's the code in the activity:
bouton_tri.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Collections.sort(productList);
}
});
EDIT 3 :
#Override
public int compareTo(Product otherProduct) {
String tmp = prix.replace(" €", "").replaceAll(" ", "");
String tmp2 = otherProduct.prix.replace(" €", "").replaceAll(" ", "");
Integer p1 = Integer.valueOf(tmp);
Integer p2 = Integer.valueOf(tmp2);
return p1.compareTo(p2);
}
I still have an error, but when I just take off " €" the value is "5 300 000", if only spaces "5300000€". But putting both together gives me this error java.lang.NumberFormatException: Invalid int: "-" ... Any ideas ? Thanks
You can make modify your Product class to implement Comparable
Before converting the String to an Integer you need to remove the €and all spaces.
public class Product implements Parcelable, Comparable<Product> {
private String prix;
//...
#Override
public int compareTo(Product otherProduct) {
String tmp = prix.replace(" €", "").replaceAll(" ", "");
String tmp2 = otherProduct.prix.replace(" €", "").replaceAll(" ", "");
Integer p1 = Integer.valueOf(tmp);
Integer p2 = Integer.valueOf(tmp2);
return p1.compareTo(p2);
}
}
Once done to sort your collection you can use : Collections.sort(...); this method will take as parameter the list of custom objects you are using in your adapter.
For example:
List<Product> l = new ArrayList();
Collections.sort(l);
Note that sorting the collection will not refresh the views of the recyclerview.
You will have to call notifyDataSetChanged() on your adapter to refresh the recyclerview:
You can do this in your main activity where you have declared your adapter :
yourAdapter.notifyDataSetChanged();
Just assuming you have List<String> sampleData object
Collections.sort(sampleData, new Comparator<String>() {
#Override
public int compare(String c1, String c2) {
return Integer.valueOf(c1) - Integer.valueOf(c2);
}
});
This will sort your data.
(int) Integer.parseInt(p2.getNumberOfRecords()) - Integer.parseInt(p1.getNumberOfRecords())
So the simple compare of an integer in a String data type would not result correctly but to parse the string first by:
int value = Integer.parseInt(string)
Try this:
Collections.sort (list, new Comparator<String> () {
#Override
public int compare (String s1, String s2) {
return s1.compareToIgnoreCase(s2);
}
});
OR
Collections.sort (list, new Comparator<String> () {
#Override
public int compare (String s1, String s2) {
//cast string price to integer
int price1 = Integer.parseInt(s1);
int price2 = Integer.parseInt(s2);
if (price1 > price1) {
return 1;
}
else if (price2 > price1) {
return -1;
}
else {
return 0;
}
}
});

How to get a part of a datastring from clicking a listview-item

I have a variable called current which holds the last clicked listview item data. The id of this data is to be used to query the db again for movies taht are similar.
The problem that current = id=17985, title=the matrix, year=1999 when all i need is the actual id-number. I have tried to use substring to only use the correct places of the string. This works for the matrix since its id is exactly 5 digits long, but as soon as i try to click movie with higher/lower amount of digits in its id of course it trips up.
String id = current.substring(4,9).trim().toString(); does not work for all movies.
Heres some code:
// search method: this is necessary cause this is the method thats first used and where the variable current is set. This is also the only method using three lines for getting data - id, title and year.
protected void search() {
data = new ArrayList<Map<String, String>>();
list = new ArrayList<String>();
EditText searchstring = (EditText) findViewById(R.id.searchstring);
String query = searchstring.getText().toString().replace(' ', '+');
String text;
text = searchquery(query);
try {
JSONObject res = new JSONObject(text);
JSONArray jsonArray = res.getJSONArray("movies");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
item = new HashMap<String, String>(2);
item.put("id",jsonObject.getString("id"));
item.put("title",jsonObject.getString("title"));
item.put("year", jsonObject.getString("year"));
data.add(item);
}
} catch (Exception e) {
e.printStackTrace();
}
aa = new SimpleAdapter(SearchTab.this, data,
R.layout.mylistview,
new String[] {"title", "year"},
new int[] {R.id.text1,
R.id.text2});
ListView lv = (ListView) findViewById(R.id.listView1);
lv.setAdapter(aa);
lv.setDividerHeight(5);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
Map<String, String> s = data.get((int) id);
current = s.toString();
}});
}
// similar method: this tries to build a list from the fetched data from "current"-string. As you can see i try to use 4,9 to only get right numbers, but this fails with others. Best would be to only to be ble to get the ID which I cant seem to do. The toast is just to see what is beeing fetched, much like a system out print.
protected void similar() {
data = new ArrayList<Map<String, String>>();
list = new ArrayList<String>();
String id = current.substring(4,9).trim().toString();
Toast.makeText(getApplicationContext(), id, Toast.LENGTH_SHORT).show();
String text;
text = similarquery(id);
try {
JSONObject res = new JSONObject(text);
JSONArray jsonArray = res.getJSONArray("movies");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
item = new HashMap<String, String>(2);
item.put("title",jsonObject.getString("title"));
item.put("year", jsonObject.getString("year"));
data.add(item);
}
} catch (Exception e) {
e.printStackTrace();
}
aa = new SimpleAdapter(SearchTab.this, data,
R.layout.mylistview2,
new String[] {"title", "year"},
new int[] {R.id.text1,
R.id.text2});
ListView lv = (ListView) findViewById(R.id.listView1);
lv.setAdapter(aa);
lv.setDividerHeight(5);
}
Use current.split(",")[0].split("=")[1]
edit - assuming of course that id is always the first in the comma separated list and will always be a name value pair delimited by '='
If you want to solve it via substring then you shouldn't use a predefined .substring(4,9). Use something like that:
String item = "id=17985, title=the matrix, year=1999";
String id = item.substring(item.indexOf("id=") + 3, item.indexOf(" ", item.indexOf("id=") + 3) - 1);
System.out.println("Your ID is: " + id);
// Works also for "test=asdf, id=17985, title=the matrix, year=1999"
It gets the String between "id=" and the next " " (space).

Categories

Resources