Java:how to group similar strings (items) to respective array (group)? - java

I have the following string "0#Aitem, 0#Aitem2, 0#Aitem3, 1#Bitem, 1#Bitem2, 2#Citem, Nitem, Nitem2".
the 0# shows group number. so Aitem, Aitem2, Aitem3 will belong to group 0. Bitem, Bitem2 in group 1. Citem in group 2. If there is no group number, they will all be place in separate group. So Nitem, Nitem2 will be placed in group 3.
I would like to create an array for each group, and place the "items" in respective group(array). So I would end up with something like
[array("Aitem,Aitem2,Aitem3"), array("Bitem, Bitem2"), array("Citem"), array("Nitem, Nitem2")]
I am guessing I need an arrayList to hold all the groups (arrays) which respectively has appropriate elements (items).
This is what I started with but I don't know if this is the best approach. The string is dynamic, so there can be any number of groups and has to follow the criteria above.
String[] x = Pattern.compile(",").split("0#item, 0#item2, 0#item3, 1#item, 1#item2, 2#item, item");
for (int ii=0; ii<x.length; ii++) {
System.out.println(i + " \"" + x[ii] + "\"");
}

My answer shows how you can use a single regex to extract both the group and the item. You can then store these in a map.
String s = "0#Aitem, 0#Aitem2, 0#Aitem3, 1#Bitem, 1#Bitem2, 2#Citem, Nitem, Nitem2";
Pattern p = Pattern.compile("(\\d*)[#]{0,1}(\\w+?)(,|$)");
Matcher m = p.matcher(s);
Map<String, List<String>> map = new TreeMap<String, List<String>>();
while(m.find()){
String group = m.group(1);
String item = m.group(2);
List<String> items = map.get(group);
if(items == null){
items = new ArrayList<String>();
map.put(group, items);
}
items.add(item);
}
//let's print it out
for(String key : map.keySet()){
System.out.println(key + " : " + map.get(key));
}
prints:
: [Nitem, Nitem2]
0 : [Aitem, Aitem2, Aitem3]
1 : [Bitem, Bitem2]
2 : [Citem]
At the moment, items with no group are keyed against an empty string. I'll leave it at as an exercise for you to handle this scenario. It should simply be a case of finding the max key and incrementing it.
I'm sure the regex can be improved too as it was written in haste.

//Create a map for storing groups
Map<String, Collection<String>> groupMap = new HashMap<String, Collection<String>>();
String[] parts = yourString.split("[, ]+"); //Split by each word
for (String part : parts) { //Go over all words
String[] subparts = part.split("#"); //Split to index and value
String groupKey;
String value;
if (subparts.length == 1) { //There is no '#' sign
groupKey = null;
value = subparts[0];
} else if (subparts.length == 2) { //There is one '#'sign
groupKey = subparts[0];
value = subparts[1];
} else {
throw new IllegalArgumentException("Can not parse string");
}
Collection<String> groupContents = groupMap.get(groupKey); //Extract list of items in this group
if (groupContents == null) { //If there was no such group yet - create one
groupMap.put(groupKey, groupContents = new ArrayList<String>());
}
groupContents.add(value); //Add item to group
}

HashMap<String,List<String> myItems = new HashMap<String,List<String>);
Then you can whatever class you want with an sting alias and store as many items as you whish.

You are on right way but I'd like to correct you a little bit.
Use the following regex to split: str.split("\\s*,\\s*"). This will support all possible spaces.
When you get separate item you have to split it again: item.split("#").
To store all this create data structure like List<List<String>>. Then do the following:
String[] parts = item.split("#");
int group = Integer.parseInt(parts[0]);
String itemName = parts[1];
List<String> groupList = allGroups.get(group);
if (groupList == null) {
groupList = new ArrayList<String>();
allGroups[group] = groupList;
}
groupList.add(itemName);
I am sorry if the code sample contains syntax errors. It is written here, on the site and should just help you to see the idea.

Another solution based on Maps.
System.out.println("###Parsing results and populating map");
String[] x = Pattern.compile("\\s*,\\s*").split(
"0#item, 0#item2, 0#item3, 1#item, 1#item2, 2#item, item");
Map<String, List<String>> result = new TreeMap<String, List<String>>();
for (int i = 0; i < x.length; i++) {
String y[] = x[i].split("#");
if (y.length > 1) {
System.out.println("group: '" + y[0] + "' item: '" + y[1] + "'");
List<String> l = result.get(y[0]);
if(l==null){
l = new ArrayList<String>();
result.put(y[0], l);
}
l.add(y[1]);
}
}
System.out.println("###Returning values stored in map, as separate arrays");
for(Entry<String,List<String>> entry: result.entrySet()){
System.out.println("Group:" + entry.getKey());
//System.out.println("Items:");
List <String> l = entry.getValue();
// This is where the final array is
String[] finalArray = l.toArray(new String[1]);
for (int i = 0; i < finalArray.length; i++) {
System.out.println(finalArray[i]);
}
}

Related

How to search for similarities in an ArrayList

I have an arrayList of String which I would like to display in a Spinner or drop down menu, but mostly what happens is I have Strings repeating, what I want to do is to search through the arrayList for similarities, if its found a string for example "Hello World" occurs 7 times in the arrayList, remove the the other 6 and assign 7 to it to show that it occurred 7 times, so my new String will be "Hello world (7)", could anyone help me on how I can implement this in my code below:
for(int i = 0; i < timesCalleddb.getAllTimesCalled(missedCall.getNumber()).size(); i++)
{
if(timesCalleddb.getAllTimesCalled(missedCall.getNumber()).get(i) ==
timesCalleddb.getAllTimesCalled(missedCall.getNumber()).get(i+1))
{
//where am guessing the implementation my problem should be
}
}
You should consider using map data structure, since you have to store the counter, otherwise, hash set would be perfect:
ArrayList<String> strs = ...;
HashMap<String, Integer> counter = new HashMap<String, Integer>();
for(String s : strs) {
counter.put(s, counter.get(s) == null ? 1 : counter.get(s) + 1);
}
for(String s : counter.keySet()) {
System.out.println(s + " (" + counter.get(s) + ")");
}
You could do the following:
Iterate over the List and make a HashMap<String, Integer> indicating how many times each String appears.
Remove duplicates from the List using list = new ArrayList<String>(new LinkedHashSet<String>(list));. Using a LinkedHashSet means that the order is kept.
Build up a new List by iterating over the List and adding either string or string + " (" + map.get(string) + ")" depending on whether map.get(string) is 1 or more than 1.
You can use this code for filtering you CustomList based on a particular String of the list. If you want to count the number of occurence, you can add some counter in the loop.
List<MyCustomObject> arrayList = new ArrayList<>();
List<MyCustomObject> result = new ArrayList<>();
Set<String> set = new HashSet<>();
for(MyCustomObject item : arrayList) {
if(set.add(item.getSomeString()) {
resultArray.add(item);
}
}
arrayList.clear();
arrayList.addAll(result);
To remove the repeated String from a List, use the following:
List<String> arrayList = new ArrayList<>();
// Your elements must be added to the arrayList, before progressing to the next step.
Set<String> set = new HashSet<>();
set.addAll(arrayList );
// Code for getting count of each String
int count = 0;
List<Integer> arrayListCount = new ArrayList<>();
for (Iterator<String> it = set.iterator(); it.hasNext(); ) {
String str = it.next();
arrayListCount.add(count , 0);
for(int i = 0; i < arrayList.size(); i++){
String s = arrayList.get(i);
if (str.equals(s)) {
arrayListCount.set(count , arrayListCount.get(count) + 1);
}
}
count++;
}
// Code for getting count ends here
arrayList.clear();
arrayList.addAll(set);
Note: The sequence of the List won't be retained.
Hope that Helps!!!

Creating a table in a for loop java

I have 2 arrays which values are words, each word in the first table is associated with a text (String), now each word from second table is showing how many times (int) is repeating in text (String). The expected table should to be like:
This is the code that I've written so far:
keyW = txtKeyword.getText();
search = textField.getText();
System.out.println("String for car = " + search);
System.out.println("String keyword = " + keyW);
btnUpload.setEnabled(false);
btnNewButton_1.setEnabled(false);
btnNewButton.setEnabled(false);
txtKeyword.setEnabled(false);
textField.setEditable(false);
//waitLabel.setVisible(true);
int iar = 0;
int item;
Map<String, Integer> dictionary = new HashMap<String, Integer>();
String[] searchArray = search.split(",");
String[] itemsFromArray1 = new String[searchArray.length];
//Keyword1 = ("Searched Key"+ "\r\n\t ");
//listKeys.add(Keyword1);
for (iar = 0; iar < searchArray.length; iar++) {
itemsFromArray1[iar] = searchArray[iar].trim();
Keyword1 = (searchArray[iar]);
//listKeys.add(Keyword1);
}
String[] items = keyW.split(",");
for (item = 0; item < searchArray.length; item++) {
WebDriver driver = new HtmlUnitDriver();
((HtmlUnitDriver) driver).setJavascriptEnabled(true);
driver.get("https://en.wikipedia.org/wiki/" + searchArray[item]);
tstr1 = driver.findElement(By.xpath("//*[#id='content']")).getText();
driver.quit();
String[] itemsFromArray = new String[items.length];
for (int i = 0; i < items.length; i++) {
itemsFromArray[i] = items[i].trim();
}
for (String string : itemsFromArray) {
int i = countWords(tstr1, string);
dictionary.put(searchArray[item].concat(string), i);
System.out.println("ARRAY " + dictionary);
}
}
private static int countWords(String tstr1, String string) {
tstr1 = tstr1.toLowerCase();
string = string.toLowerCase();
int posCount = 0;
String positive = string;
Pattern positivePattern = Pattern.compile(positive);
Matcher matcher = positivePattern.matcher(tstr1);
while (matcher.find()) {
posCount++;
}
return posCount;
}
I tried to achieve this with Map<String, Integer> dictionary = new HashMap<String, Integer>(); but the results (dictionary.put(searchArray[item], i);) are wrong. Can anyone give me an idea how to solve this. Thanks!
****UPDATE****
Now the results in the console is something like this:
ARRAY { boyanimal=4, catfree=18, catanimal=60, boyfree=2, catgender=0, boygender=6, windowfree=5}
ARRAY { boyanimal=4, catfree=18, catanimal=60, boyfree=2, windowanimal=4, catgender=0, boygender=6, windowfree=5}
ARRAY { boyanimal=4, catfree=18, catanimal=60, boyfree=2, windowanimal=4, catgender=0, boygender=6, windowgender=0, windowfree=5}
There are values that are repeting. How to make to show just like a table?
Try using this:
Map<String, Integer> tableMap = new HashMap<String, Integer>();
keep the key as:
tableMap.put("Word1-Search1",23);
Using this, you will always have a unique combination for each key.
I hope you don't want to store the data in a data structure? Instead you should use a 2 dimensional String array to store it.
Answering your latest update:
I think you're getting multiple copies because of this line.
dictionary.put(searchArray[item].concat(string), i);
I think the concat is being applied to the entire row of elements. I would use my debugger to analyze this and see what the value of searchArray[item] is and what the value of string is.

Using Java's built-in Set classes to count EACH(keyword) unique element in List values from a list

Given a list that could contain duplicates (like the one below), I need to be able to count Each(keyword) number of unique elements.
List<String> list = new ArrayList<String>();
Set<String> set = new HashSet<String>();
list.add("M1");
list.add("M1");
list.add("M2");
list.add("M3");
set.addAll(list);
System.out.println(set.size());
How do I get the count each unique element from the List?
That means i want to know how many "M1" contains in List(list), how many "M2", etc.
The result should be the following:
2 M1
1 M2
1 M3
You are looking for Map<String, Integer> data structure, not Set
Something like
for(iterating over something){
Integer count =map.get(value);
if( count == null){
map.put(value, 1);
} else{
count++;
map.put(value, count);
}
}
Map is the data structure that maps unique to value
I think you are looking for something like this (I didn't compile it, but it should get you going in the right direction):
List<String> list = ArrayList<>();
Map<String, Integer> counts = new HashMap<>();
// Fill list with values....
for (String item:list) {
Integer count = counts.get(item);
if (count == null) {
// This is the first time we have seen item, so the count should be one.
count = 1;
} else {
// Increment the count by one.
count = count + 1;
}
counts.put(item, count);
}
// Print them all out.
for (Entry<String, Integer> entry : counts.entrySet()) {
System.out.println(entry.getValue() + " " + entry.getKey());
}
Set won't help you in this case, you need a Map:
List<String> list = new ArrayList<String>();
Set<String> set = new HashSet<String>();
list.add("M1");
list.add("M1");
list.add("M2");
list.add("M3");
// ...
Map<String, Integer> counts = new HashMap<String, Integer>();
for(String element: list) {
int currentCount;
if(counts.contains(element)) {
currentCount = counts.get(element) + 1;
} else {
currentCount = 1;
}
counts.put(element, currentCount);
}
// ...
for(String element: counts.keySet()) {
System.out.println("element: " + element + ", times appeared: " + counts.get(element));
}
means You want to know how many "M1" contains in List(list), how many "M2", instead of using set interface, you can use the Map interface because Map contain the key, value pair format ,i.e. Map data structure.
Map<key,Value>
Much easier way: use Collections.frequency()
System.out.println("M2: "+Collections.frequency(list,"M2");
will output
M2: 1

How do I compare 2 arraylists in a Hashmap?

I have an arraylist called fetchContactName() which returns all names (31) in my contact list, an arraylist called fetchContactNumbers() which returns all phone numbers (31) associated with fetchContactName(), and an arraylist called newList which has all the numbers that sent me text messages (6).
I was trying to change the phone numbers in newList by looking for the same numbers in fetchContactNumbers(). When there was a match, I would then index the position in fetchContactNumbers() and use that index to get the name at the same position in fetchContactName(). From there, I would replace the numbers in newList with the names in fetchContactName() according to the indexed position.
This is an example I've made that executes as stated above:
http://pastebin.com/pApHNkXa
The problem with the above example is that when I apply it to my listview, only one element in the list is changed to a name. More oddly, newList.get(3) is the only one that changed to a name. Not newList at positions 0, 1, 2, 4 and 5.
From others suggests, how can I use a HashMap to give the same expected result as the example given above? I was told to use fetchContactNumbers() and fetchContactNames() in the Hashmap then use the HashMap to compare with newList, but I cant find any source to achieve this.
UPDATE:
Here is the working code for my HashMap, but the results are still the same as above:
for (String str : fetchContactNames()) {
contactNameNew += str + " ";
}
for (String str2 : fetchContactNumbers()) {
contactNumberNew += str2 + " ";
}
//String to split
String temp[];
String temp2[];
String delimiter = " ";
temp = contactNameNew.split(delimiter);
temp2 = contactNumberNew.split(delimiter);
HashMap<String, String> contacts = new HashMap<String, String>();
contacts.put(contactNameNew, contactNumberNew);
for(int i = 0; i < fetchContactNames().size(); i++){
contacts.put(temp[i], temp2[i]);
}
Iterator<Entry<String, String>> iterator = contacts.entrySet().iterator();
while(iterator.hasNext()){
Entry<String, String> entry = iterator.next();
int position = getPosition(newlist, entry.getValue());
if (newlist.contains(entry.getValue())) {
newlist.set(position, entry.getKey());
}
}
I think it will be better if I changed your code and answered...
import java.util.ArrayList;
import java.util.HashMap;
public class StringT {
public static void main(String[] args) {
// alpha would represent fetchContactNames()
ArrayList<String> alpha = new ArrayList<String>();
// bravo would represent fetchContactNumbers()
HashMap<String, String> bravo = new HashMap<String, String>();
// charlie would represent newList
ArrayList<String> charlie = new ArrayList<String>();
bravo.put("1", "One"); charlie.add("5");
bravo.put("2", "Two"); charlie.add("1");
bravo.put("3", "Three"); charlie.add("3");
bravo.put("4", "Four"); charlie.add("4");
bravo.put("5", "Five"); charlie.add("2");
// this will print charlie just as you see above
for(int i = 0; i < charlie.size(); i ++){
System.out.println(charlie.get(i));
}
System.out.println("---------------------");
// this will print charlie with the numbers replaced as names
for(int i = 0; i < charlie.size(); i++){
String value;
if((value = bravo.get(charlie.get(i))) != null){
charlie.set(i, value);
}
}
for(int i = 0; i < charlie.size(); i ++){
System.out.println(charlie.get(i));
}
}
}
your code is working that u placed here http://pastebin.com/pApHNkXa i tried it in android and its working alright its giving output as five, two, seven, three .

Manipulating a user's input

So I'm trying to manipulate the user's input in such a way that when I find a certain string in his input I turn that into a variable and replace the string with the name of the variable. (jumbled explanation I know, maybe an example will make it more clear).
public class Test {
static List<String> refMap = new ArrayList<String>();
public static void main(String[] args) {
String x = "PROPERTY_X";
String y = "PROPERTY_Y";
refMap.add(x);
refMap.add(y);
String z = "getInteger("PROPERTY_X)";
String text = "q=PROPERTY_X+10/(200*PROPERTY_X)";
String text1 = "if(PROPERTY_X==10){"
+ "j=1;"
+ "PROPERTY_X=5; "
+ "if(true){"
+ "m=4/PROPERTY_X"
+ "}"
+ "}";
detectEquals(text);
}
public static String detectEquals(String text) {
String a = null;
text = TestSplitting.addDelimiters(text);
String[] newString = text.split(" ");
List<String> test = Arrays.asList(newString);
StringBuilder strBuilder = new StringBuilder();
HashMap<String, Integer> signs = new HashMap<String, Integer>();
HashMap<String, Integer> references = new HashMap<String, Integer>();
List<String> referencesList = new ArrayList<String>();
List<Integer> indexList = new ArrayList<Integer>();
int index = 0;
for (int i = 0; i < test.size(); i++) {
a = test.get(i).trim();
//System.out.println("a= " + a);
strBuilder.append(a);
index = strBuilder.length() - a.length();
if (a.equals("=")) {
signs.put(a, index);
indexList.add(index);
// System.out.println("signs map--> : "+signs.get(a));
}
if (refMap .contains(a)) {
references.put(a, index);
// System.out.println("reference index-> "+references.get(a));
// System.out.println("reference-> "+references.toString());
}
}
//stuck here
for (String s : references.keySet()) {
//System.out.println("references-> " + s);
int position = references.get(s);
for (int j : indexList) {
if (j <= position) {
System.out.println(j);
}
}
//strBuilder.insert(j - 1, "temp1=\r\n");
}
System.out.println(strBuilder);
return a;
}
Say the user inputs the content of the string "text", I'm trying to parse that input so when I find "PROPERTY_X", I want to create a variable out of it and place it right before the occurrence of text, and then replace "PROPERTY_X" with the name of the newly created variable.
The reason I'm also searching for "=" sign is because I only want to do the above for the first occurrence of "PROPERTY_X" in the whole input and then just replace "PROPERTY_X" with tempVar1 wherever else I find "PROPERTY_X".
ex:
tempVar1=PROPERTY_X;
q=tempVar1+10/(200*tempVar1);
Things get more complex as the user input gets more complex, but for the moment I'm only trying to do it right for the first input example I created and then take it from there :).
As you can see, I'm a bit stuck on the logic part, the way I went with it was this:
I find all the "=" signs in the string (when I move on to more complex inputs I will need to search for conditions like if,for,else,while also) and save each of them and their index to a map, then I do the same for the occurrences of "PROPERTY_X" and their indexes. Then I try to find the index of "=" which is closest to the index of the "PROPERTY_X" and and insert my new variable there, after which I go on to replace what I need with the name of the variable.
Oh the addDelimiters() method does a split based on some certain delimiters, basically the "text" string once inserted in the list will look something like this:
q
=
PROPERTY_X
+
10
etc..
Any suggestions are welcome.

Categories