Replace strings populated in an ArrayList<String> with other values - java

I am currently working on a project where I need to check an arraylist for a certain string and if that condition is met, replace it with the new string.
I will only show the relevant code but basically what happened before is a long string is read in, split into groups of three, then those strings populate an array. I need to find and replace those values in the array, and then print them out. Here is the method that populates the arraylist:
private static ArrayList<String> splitText(String text)
{
ArrayList<String> DNAsplit = new ArrayList<String>();
for (int i = 0; i < text.length(); i += 3)
{
DNAsplit.add(text.substring(i, Math.min(i + 3, text.length())));
}
return DNAsplit;
}
How would I search this arraylist for multiple strings (Here's an example aminoAcids = aminoAcids.replaceAll ("TAT", "Y");) and then print the new values out.
Any help is greatly appreciated.

In Java 8
list.replaceAll(s-> s.replace("TAT", "Y"));

There is no such "replace all" method on a list. You need to apply the replacement element-wise; the only difference vs doing this on a single string is that you need to get the value out of the list, and set the new value back into the list:
ListIterator<String> it = DNAsplit.listIterator();
while (it.hasNext()) {
// Get from the list.
String current = it.next();
// Apply the transformation.
String newValue = current.replace("TAT", "Y");
// Set back into the list.
it.set(newValue);
}
And if you want to print the new values out:
System.out.println(DNAsplit);

Why dont you create a hashmap that has a key-value and use it during the load time to populate this list instead of revising it later ?
Map<String,String> dnaMap = new HashMap<String,String>() ;
dnaMap.push("X","XXX");
.
.
.
dnaMap.push("Z","ZZZ");
And use it like below :
//Use the hash map to lookup the temp key
temp= text.substring(i, Math.min(i + 3, text.length()));
DNAsplit.add(dnaMap.get(temp));

Related

Return the updated ArrayList<Characters> after removing the specified element at the index

I am trying to find out if there is a possibility of returning the updated ArrayList after removing the specified element at the index in a single line so that I can pass it on to the recursive function.
Below is a snippet of my code which tries to generate all valid parenthesis combinations given n pairs of "()" brackets.
My concern is in the recursive function call "findAllCombinations" where after some validations I want to remove one character at each recursive call from the arrayList courceSet. However sourceSet.remove(index) returns a character. Instead I want to pass the updated list after removing the character in one line. Is it possible ?
Note : The line below is syntactically wrong and just used for better illustration.
findAllCombinations(sourceSet.remove(index), soFar + singleBracket, singleBracket); .
I did go through the official documentation but did not find any help.
Any help is appreciated, and thanks for your time.
public class GenerateParenthesis {
char singleBracket;
List<String> answerSet = new ArrayList<String>();
char[] repoSet = {'(',')'};
public List<String> generateParenthesis(int n) {
String soFar = "(";
List<Character> sourceSet = new ArrayList<Character>();
for(int i = 0;i<n;i++){
sourceSet.add('(');
sourceSet.add(')');
}
findAllCombinations(sourceSet,soFar,'(');
return answerSet;
}
public void findAllCombinations(List<Character> sourceSet,String soFar,Character toRemove){
if(sourceSet.isEmpty()){
answerSet.add(soFar); // append to a answer set list containing all combinations
return;
}
for(int i = 0;i<2;i++){
singleBracket = repoSet[i];
int index = sourceSet.indexOf(singleBracket);
if(index!=-1) {
findAllCombinations(sourceSet.remove(index), soFar + singleBracket, singleBracket);
}
}
}
public static void main(String args[]){
GenerateParenthesis gp = new GenerateParenthesis();
List<String> ans = new ArrayList<String>();
ans = gp.generateParenthesis(3);
}
}
ArrayList (likely to most List implementations) is a mutable data structure: calling remove you modify the list rather than returning a new list without the removed element.
If you want the latter behavior, the quick and easy way is to do a copy of the list.
// (inside the if...)
// pass the original list to the constructor to make a copy
List<Character> sourceSetCopy = new ArrayList<>(sourceSet);
// modify the copy
sourceSetCopy.remove(index);
// use the modified copy
findAllCombinations(sourceSetCopy, soFar + singleBracket, singleBracket);

How can I add a string one at a time to a HashMap<Integer, List<String>>?

This function loops through a dictionary (allWords) and uses the
getKey function to generate a key. wordListMap is a HashMap> so I need to loop through and put the key and and a List. If there is not a list I put one if there is I just need to append the next dictionary word. This is where I need help. I just can't figure out the syntax to simply append the next word to the list that is already there. Any Help would be appreciated.
public static void constructWordListMap() {
wordListMap = new HashMap<>();
for (String w : allWords) {
int key = getKey(w);
if (isValidWord(w) && !wordListMap.containsKey(key)) {
List list = new ArrayList();
list.add(w);
wordListMap.put(key, list);
} else if (isValidWord(w) && wordListMap.containsKey(key)) {
wordListMap.put(key, wordListMap.get(key).add(w));
}
}
}
map.get(key).add(value)
Simple as that.
So I've gathered that you want to, given HashMap<Integer, List<String>>, you'd like to:
create a List object
add String objects to said List
add that List object as a value to be paired with a previously generated key (type Integer)
To do so, you'd want to first generate the key
Integer myKey = getKey(w);
Then, you'd enter a loop and add to a List object
List<String> myList = new List<String>;
for(int i = 0; i < intendedListLength; i++) {
String myEntry = //wherever you get your string from
myList.add(myEntry);
}
Lastly, you'd add the List to the HashMap
myHash.put(myKey, myList);
Leave any questions in the comments.
else if (isValidWord(w) && wordListMap.containsKey(key)) {
wordListMap.put(key, wordListMap.get(key).add(w));
}
If you want to add a new value to your list, you need to retrieve that list first. In the code above, you are putting the return value of add into the table (which is a boolean), and that is not what you want.
Instead, you will want to do as Paul said:
else if (isValidWord(w) && wordListMap.containsKey(key)) {
wordListMap.get(key).add(w);
}
The reason this works is because you already added an ArrayList to the table earlier. Here, you are getting that ArrayList, and adding a new value to it.

Finding common between Array-list of Strings

I've array-list "mArrayListvarinats" of String which contains pipe separated strings like
225356175|225356176|225356177|225356178|225356179|225356180|225356181|225356182|225356183|225356184|225356185|225356186|225356187|225356188|225356189|225356190|225356191|225356192
The size of mArrayListvarinats may be 0 upto n Now I want to find out common string between those Strings from mArrayListvarinats.
for ex. if it's size is two the code may be like as follows.
String temp[] = mArrayListvarinats.get(0).split("\\|");
String temp1[] = mArrayListvarinats.get(1).split("\\|");
and then loop will work on both the arrays to get common one.But how to achieve it for any no of size inside the loop as those temp arrays will be generated in the loop on mArrayListvarinats?
Something like this should work :
HashSet<String> allStrings = new HashSet<String>();
HashSet<String> repeatedStrings = new HashSet<String>();
for(String pipedStrings: mArrayListvarinats){
String temp[] = pipedStrings.split("\\|");
for(String str : temp){
if(!allStrings.add(str)){
repeatedStrings.add(str);
}
}
}
This way, you will have your HashSet allStrings that contains all your unique strings. And the other HashSet repeatedStrings which contains all the strings that appears more than once.
Try this short version:
public static void main(String[] args) {
List<String> a = new ArrayList<>(asList("225356176|225356177|225356178".split("\\|")));
List<String> b = new ArrayList<>(asList("225356175|225356176|225356177".split("\\|")));
a.retainAll(b);
b.retainAll(a);
System.out.println(b);
}
OUTPUT:
[225356176, 225356177]
Iterate through each of them and put them in a HashSet. If you get false while adding it means it's already there. You can put it in a separate Hashset. this way you will get a hashset of all unique string and an another hashset of strings that occured multiple times
Set<String> set=new HashSet<String>();
for (int i = 0; i < temp.length; i++) {
set.add(str[i]);
}
for (int i = 0; i < temp1.length; i++) {
set.add(str1[i]);
}
The set will contain common strings.
If you are only interested in getting common strings found in mArrayListvarinats variable, then you should use Set data structure. Set in java will only contain unique entries. From the example strings it sounds that you are collecting string which has numeric values. So there won't be any problem due to that. But if you are collecting alpha numeric value then you need to take care of alphabet's case, as Set collects values which are case sensitive. So for Set A is not equal to a.
This will find common among all your lists.
List<String> common = Arrays.asList(mArrayListvarinats.get(0).split("\\|"));
for(String varinats: mArrayListvarinats){
List<String> items = Arrays.asList(varinats.split("\\|"));
common = ListUtils.intersection(items,common);
}
But for this you have to use Apache commons collection library , which I hope is not a issue for you :)
Below code will return you the frequency of each string present in the array.
public static void main(String[] args) {
String mArrayListvarinats = "225356175,225356176,225356177,225356178,225356179,225356180,225356181,225356182,225356183,225356184,225356185,225356186,225356187,225356188,225356189,225356190,225356191,225356192,225356192";
List<String> list = Arrays.asList(mArrayListvarinats.split(","));
Set<String> uniqueWords = new HashSet<String>(list);
for (String word : uniqueWords) {
System.out.println(word + ": " + Collections.frequency(list, word));
}
}
String with frequency more than 1 are duplicates/common. You can take actions based on frequency.

Java Parsing Using Hmap

I am new to Java. I want to Parse the data which is in this Format
Apple;Mango;Orange:1234;Orange:1244;...;
There could be more than one "Orange" at any point of time. Numbers (1,2...) increase and accordingly as the "Orange".
Okay. After splitting it, Lets assume I have stored the first two data(Apple, Orange) in a variable(in setter) to return the same in the getter function. And now I want to add the value(1234,1244....etc) in the 'orange' thing into a variable to return it later. Before that i have to check how many oranges have come. For that, i know i have to use for loop. But don't know how to store the "Value" into a variable.
Please Help me guys.
String input = "Apple;Mango;Orange:1234;Orange:1244;...;"
String values[] = input.split(";");
String value1 = values[0];
String value2 = values[1];
Hashmap< String, ArrayList<String> > map = new HashMap<String, ArrayList<String>>();
for(int i = 2; i < values.length; i = i + 2){
String key = values[i];
String id = values[i+1];
if (map.get(key) == null){
map.put(key, new ArrayList<String>());
}
map.get(key).add(id);
}
//for any key s:
// get the values of s
map.get(s); // returns a list of all values added
// get the count of s
map.get(s).size(); // return the total number of values.
Let me try to rephrase the question by how I interpreted it and -- more importantly -- how it focuses on the input and output (expectations), not the actual implementation:
I need to parse the string
"Apple;Mango;Orange:1234;Orange:1244;...;"
in a way so I can retrieve the values associated (numbers after ':') with the fruits:
I should receive an empty list for both the Apple and Mango in the example, because they have no value;
I should receive a list of 1234, 1244 for Orange.
Of course your intuition of HashMap is right on the spot, but someone may always present a better solution if you don't get too involved with the specifics.
There are a few white spots left:
Should the fruits without values have a default value given?
Should the fruits without values be in the map at all?
How input errors should be handled?
How duplicate values should be handled?
Given this context, we can start writing code:
import java.util.*;
public class FruitMarker {
public static void main(String[] args) {
String input = "Apple;Mango;Orange:1234;Orange:1244";
// replace with parameter processing from 'args'
// avoid direct implementations in variable definitions
// also observe the naming referring to the function of the variable
Map<String, Collection<Integer>> fruitIds = new HashMap<String, Collection<Integer>>();
// iterate through items by splitting
for (String item : input.split(";")) {
String[] fruitAndId = item.split(":"); // this will return the same item in an array, if separator is not found
String fruitName = fruitAndId[0];
boolean hasValue = fruitAndId.length > 1;
Collection<Integer> values = fruitIds.get(fruitName);
// if we are accessing the key for the first time, we have to set its value
if (values == null) {
values = new ArrayList<Integer>(); // here I can use concrete implementation
fruitIds.put(fruitName, values); // be sure to put it back in the map
}
if (hasValue) {
int fruitValue = Integer.parseInt(fruitAndId[1]);
values.add(fruitValue);
}
}
// display the entries in table iteratively
for (Map.Entry<String, Collection<Integer>> entry : fruitIds.entrySet()) {
System.out.println(entry.getKey() + " => " + entry.getValue());
}
}
}
If you execute this code, you will get the following output:
Mango => []
Apple => []
Orange => [1234, 1244]

Sorting a list of maps within before this while loop runs out(Java)

A database call is made and result is a bunch of rows of two string columns of type A and B. e.g. (x_a, y_b), (x_a, y1_b), (x2_a,y_b)
The idea is to come up with a list of maps like {(x_a,{y_b,y1_b}), (x2_a,{y_b})} where the objects of type A are not repeated and to do this while pulling the results from a database.
Here's what I tried:
int i =0;
List<String> type2 = new ArrayList<String>();
Map<String,List<String>> type1_type2 = new HashMap<String,List<String>>();
List<Map> list_type1_type2 = new ArrayList<Map>();
String [] type1Array = new String[100];
String [] type2Array = new String[100];
int trackStart = 0;
while (res.next()){
String type1 = res.getString(1);
String type2 = res.getString(2);
type1Array[i]=type1;
type2Array[i] = type2;
if(i>0 && !type1Array[i].equals(type2Array[i-1])){
int trackStop = i;
for(int j = trackStart; j<trackStop;j++){
type2.add(type2Array[j]);
}
type1_type2.put(type1Array[i-1], type2);
list_type1_type2.add(type1_type2);
//debugging stuff
String x = list_type1_type2.toString();
System.out.println(x);
System.out.println(" printing because "+ type1Array[i]+" is not equal to " + type1Array[i-1]);
type2 = new ArrayList<String>();
type1_type2 = new HashMap<String,List<String>>();
trackStart=i;
}
i++;
}
This method does not work when the last type1 values of the result object are the same.
Is there a way to do this in the same spirit (within the while(res.next)) without first storing the results of the database call in separate arrays or adding an extra for loop outside the while loop to "patch it up"?
The simple way to do this is to use a Guava / Google Collections SetMultiMap. This is essentially a mapping from a key (your 'A' objects) to a set of values (your 'B' objects).
[I'm not going to try to code it for you. Your current code is too horrible to read ... unless you were paying me :-) ]
However, a better idea would be to get the database to do the collation. If you can do that, you will reduce the amount of (redundant) data that gets send across the database connection ... assuming that you are using JDBC.
If you don't want duplicates like {x_a:[y_b, y_b]} then use a set as the value of your map:
Map<String,Set<String>> type1_type2;
I don't know what the other various list and arrays are for. You can probably just get by with the type1_type2 map. Process each (x, y) in pseudo-code:
Set s = type1_type2.get(x)
if s == null:
s = new Set()
type1_type2.put(x, s)
s.add(y)

Categories

Resources