I am trying to read a file which has say
Name,Date,Place
Tom,1/1/2010,America
Dick,2/2/2011,China
Harry,3/3/2012,Germany
And adds the column headers to a String and the values to an ArrayList.
HashMap<String columnName ,ArrayList<String> Value>
So the program should run like,
if(lineNumber == 1)
{
interate through values and create headers
}
else
add values to corresponding header list
My problem is I do not know how I can reference the arraylist in the else part of the code.
If anybody has done something similar I would like to hear from you !
Edit
So I have something like this so far,
public void consumeLine(String path,int lineNumber,List line){
if(lineNumber == 1)
{
ListIterator listIterator = line.listIterator();
while(listIterator.hasNext())
{
hashMap.put(listIterator.next().toString(),new ArrayList<String>());
}
}
You want to create an ordered list of the column names, and iterate through that as you iterate through the values in each row.
Something like this (untested code!):
ListIterator listIterator = line.listIterator();
if(lineNumber == 1)
{
while(listIterator.hasNext())
{
String key = listIterator.next().toString();
keyList.add(key); // keyList is a List<String> instance field.
hashMap.put(key, new ArrayList<String>());
}
} else {
Iterator<String> keyIterator = keyList.iterator();
while(keyList.hasNext() && listIterator.hasNext())
{
String key = keyList.next();
String value = listIterator.next();
ArrayList<String> values = hashMap.get(key);
values.add(value);
}
}
Try it:
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
int lineNumber = 1;
String[] columnName = null;
ArrayList<String[]> value = new ArrayList<String[]>(); // temp array
String line;
String[] arr;
while (reader.ready())
if (!(line = reader.readLine()).isEmpty()) {
arr = line.split("\\s+");
if (lineNumber == 1)
columnName = arr;// create headers
else
value.add(arr);// create values
lineNumber++;
}
// transform data
for (int i = 0; i < columnName.length; i++) {
ArrayList<String> ar = new ArrayList<String>();
for (int j = 0; j < value.size(); j++)
ar.add(value.get(j)[i]);
map.put(columnName[i], ar);
}
System.out.println(map);
}
Related
For an assignment I have been asked to find the largest group of anagrams in a list. I believe I would have to have an accumulation loop inside of another loop that keeps track of the largest number of items. The problem is that I don't know how to count how many of each anagram I have. I have been able to sort the array into groups based on their anagrams. So from the index 1-3 is one anagram, 4-10 is another, etc. How do I search through and count how many of each anagram I have? Then compare each one to the previous count.
Sample of the code:
public static String[] getLargestAnagramGroup(String[] inputArray) {
ArrayList<String> largestGroupArrayList = new ArrayList<String>();
if (inputArray.length == 0 || inputArray == null) {
return new String[0];
}
insertionSort(inputArray, new AnagramComparator());
String[] largestGroupArray = new String[largestGroupArrayList.size()];
largestGroupArrayList.toArray(inputArray);
System.out.println(largestGroupArray);
return largestGroupArray;
}
UPDATE: This is how we solved it. Is there a more efficient way?
public static String[] getLargestAnagramGroup(String[] inputArray) {
int numberOfAnagrams = 0;
int temporary = 1;
int position = -1;
int index = 0;
if (inputArray == null) {
return new String[0];
}
insertionSort(inputArray, new AnagramComparator());
for (index = 0; index < inputArray.length - 1; index++) {
if (areAnagrams(inputArray[index], inputArray[index + 1])) {
temporary++;
} else {
if (temporary > numberOfAnagrams) {
numberOfAnagrams = temporary;
position = index;
temporary = 1;
} else if (temporary < numberOfAnagrams) {
temporary = 1;
}
}
}
if (temporary > numberOfAnagrams) {
position = index;
numberOfAnagrams = temporary;
}
String[] largestArray = new String[numberOfAnagrams];
for (int startIndex = position - numberOfAnagrams + 1, i = 0; startIndex <= position; startIndex++, i++) {
largestArray[i] = inputArray[startIndex];
}
return largestArray;
}
Here is a piece of code to help you out.
public class AnagramTest {
public static void main(String[] args) {
String[] input = {"test", "ttes", "abcd", "dcba", "dbac"};
for (String string : getLargestAnagramGroup(input)) {
System.out.println(string);
}
}
/**
* Gives an array of Strings which are anagrams and has the highest occurrence.
*
* #param inputArray
* #return
*/
public static String[] getLargestAnagramGroup(String[] inputArray) {
// Creating a linked hash map to maintain the order
Map<String, List<String>> map = new LinkedHashMap<String, List<String>>();
for (String string : inputArray) {
char[] charArray = string.toCharArray();
Arrays.sort(charArray);
String sortedStr = new String(charArray);
List<String> anagrams = map.get(sortedStr);
if (anagrams == null) {
anagrams = new ArrayList<String>();
}
anagrams.add(string);
map.put(sortedStr, anagrams);
}
Set<Entry<String, List<String>>> entrySet = map.entrySet();
List<String> l = new ArrayList<String>();
int highestAnagrams = -1;
for (Entry<String, List<String>> entry : entrySet) {
List<String> value = entry.getValue();
if (value.size() > highestAnagrams) {
highestAnagrams = value.size();
l = value;
}
}
return l.toArray(new String[l.size()]);
}
}
The idea is to first find the anangrams. I am doing that using a sorting the string's character array and using the LinkedhashMap.
Then I am storing the original string in the list which can be used to print or reuse as a result.
You have to keep counting the number of times the an anagram occurs and that value can be used solve your problem
This is my solution in C#.
public static string[] LargestAnagramsSet(string[] words)
{
var maxSize = 0;
var maxKey = string.Empty;
Dictionary<string, List<string>> set = new Dictionary<string, List<string>>();
for (int i = 0; i < words.Length; i++)
{
char[] temp = words[i].ToCharArray();
Array.Sort(temp);
var key = new string(temp);
if (set.ContainsKey(key))
{
set[key].Add(words[i]);
}
else
{
var anagrams = new List<string>
{
words[i]
};
set.Add(key, anagrams);
}
if (set[key].Count() > maxSize)
{
maxSize = set[key].Count();
maxKey = key;
}
}
return string.IsNullOrEmpty(maxKey) ? words : set[maxKey].ToArray();
}
This is my List<String[]> object, that i have to put in a hashmap - Map<String, List<String>>.
The first array of Strings, are my keys.
I have to put other arrays in order - First Row = First Key, Second Row = Second key ecc..
I have tried to write by me an algorithm, but don't know how to finish
public Map<String, List<String>> getMapWithListOfStrings() throws IOException {
Map<String, List<String>> returningMap = new HashMap<>();
List<String[]> readAll = csvReader.readAll();
for (int i = 0; i < 1; i++) {
for (String get : readAll.get(i)) {
returningMap.put(get, new ArrayList<String>());
}
}
for (int i = 0; i < returningMap.size(); i++) {
}
return returningMap;
}
Is this what you needed?
public Map<String, List<String>> getMapWithListOfStrings() {
Map<String, List<String>> returningMap = new HashMap<>();
List<String[]> readAll = csvReader.readAll();
String[] keys = readAll.get(0);
for (int i = 0; i < keys.length; i++) {
String key = keys[i];
List<String> value = new ArrayList<>();
// j = 0 is excluded - it contains the keys, not the values
for(int j = 1; j < readAll.size(); j++) {
String iValue = readAll.get(j)[i];
value.add(iValue);
}
returningMap.put(key, value);
}
return returningMap;
}
I am not absolutely sure whether I fully understand your problem, but I guess something like the following (code is untested) should solve your issue.
String[] keys = readAll.get(0);
// Make sure there is one key per line of data.
if(keys.length!=readAll.size()-1) {
throw new IllegalStateException("Invalid CSV format!");
}
// Put all the data lines together with their respective key into your Map.
for(int i=1;i<readAll.size();i++) {
returningMap.put(keys[i-1],Arrays.asList(readAll.get(i)));
}
I have the following code. What I want to do is to have an ArrayList filled using the permutation function, keep that Array in a HashMap, and start the process all over again (basically fill the HashMap with ArrayList for each key). I posted the code below however it does not work. I think this is because It's storing the same reference to the list I have declared instead of making a copy of it. I'm a C scrub and a Java newbie so any help is appreciated!
public class Anagrams
{
public static HashMap<String, ArrayList<String>> permutacii = new HashMap<String, ArrayList<String>>();
public static ArrayList<String> tempList = new ArrayList<String>();
private static void permutation(String prefix, String str)
{
int n = str.length();
if (n == 0)
tempList.add(prefix);
else
{
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i),
str.substring(0, i) + str.substring(i+1));
}
}
public static void main(String[] args) {
findAll(System.in);
}
public static void findAll(InputStream inputStream)
{
Scanner scanner = new Scanner(inputStream);
while(scanner.hasNextLine())
{
String line = scanner.nextLine();
permutation("", line);
permutacii.put(line, tempList);
tempList.clear();
}
}
}
You only have one List of which you store multiple references in the HashMap. And you clear that List at the end of each iteration.
One possible way to fix your problem :
while(scanner.hasNextLine())
{
String line = scanner.nextLine();
tempList = new ArrayList<String>();
permutation("", line);
permutacii.put(line, tempList);
}
Though I think the code would be more readable if you make tempList a local variable and pass it as an argument to the permutation method :
while(scanner.hasNextLine())
{
String line = scanner.nextLine();
ArrayList<String> tempList = new ArrayList<String>();
permutation("", line, tempList);
permutacii.put(line, tempList);
}
and modify the permutation accordingly :
private static void permutation(String prefix, String str, ArrayList<String> tempList)
{
int n = str.length();
if (n == 0)
tempList.add(prefix);
else
{
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i),
str.substring(0, i) + str.substring(i+1),
tempList);
}
}
I have a ArrayList: ArrayList<String> buffer = new ArrayList<String>();
How can I take duplicated values from ArrayList?
Example:
fsfs.txt
erwre.txt
wery.txt
wtrtr.txt
erwre.txt
qweq.txt
My attempts:
With cycles:
for(int i = 0; i < buffer.size(); i++) {
for(int j = i + 1; j < buffer.size(); j++) {
if( buffer.get(i).equals(buffer.get(j)) ) {
bufferTemp.add(j, buffer.toString() );
j--;
}
}
}
With iterator:
Iterator<String> i = buffer.iterator();
Iterator<String> j = buffer.iterator();
j.next();
while(i.hasNext() && j.hasNext()) {
if( i.next().equals(j.next() )
System.out.println(i.next());
}
Also I try to use Comparable, Comparator and other ways but it don't work.
You can create a Set passing the your list as a argument. Set will take care of duplicates.
private static List<String> list = new ArrayList<String>();
public static void main(String[] args) {
list.add("aaa.txt");
list.add("aaa.txt");
list.add("aaa.txt");
list.add("bbb.txt");
list.add("ccc.txt");
list.add("ccc.txt");
Set<String> set = new HashSet<String>(list);
System.out.println(set);
}
If I understand you correctly, you use Java and want to get the duplicates of an ArrayList.
If you use Strings, then you can just sort the List and compare in a loop the previous with the current element. Look at this (Java 7):
ArrayList<String> list = new ArrayList<>();
list.add("fsfs.txt");
list.add("erwre.txt");
list.add("wery.txt");
list.add("wtrtr.txt");
list.add("erwre.txt");
list.add("qweq.txt");
// Sort the list
Collections.sort(list);
// Test if List was sorted correctly
for(String s : list)
{
System.out.println(s);
}
System.out.println("\n*** Now try to get duplicates ***\n");
Iterator<String> listIt = list.iterator();
String prev = "";
boolean foundDuplicate = false;
while(listIt.hasNext())
{
String current = listIt.next();
if(current.equals(prev))
foundDuplicate = true;
else
foundDuplicate = false;
if(foundDuplicate)
{
// Duplicate found!
System.out.println(current);
}
prev = current;
}
Output should be:
erwre.txt
erwre.txt
fsfs.txt
qweq.txt
wery.txt
wtrtr.txt
*** Now try to get duplicates ***
erwre.txt
OK so here is some logic thinking... What I am trying to do is loop through strings until I hit a null/empty string.. then STOP. All while putting those strings inside a string array...
Here is a sample of the code. I know it's wrong but hopefully to give you an idea of what I am trying to achieve:
int i;
wepN = new String[100];
int wepQty = 0;
boolean anyLeft = true;
while (anyLeft == true) {
for(i = 0;i < 100;i++) {
if (data.getItems().get(i).getName() == null) {
anyLeft = false;
System.out.println(data.getItems().get(i).getName() + " -NO MOARE");
}
wepN[i] = data.getItems().get(i).getName();
wepQty++;
}
}
You can use break to exit a for loop, same as you would a switch statement:
String[] wepN = new String[100];
int wepQty = 0;
for (int i=0; i < wepN.length; i++) {
if (data.getItems().get(i).getName() == null || "".equals(data.getItems().get(i).getName())) {
System.out.println(data.getItems().get(i).getName() + " -NO MOARE");
break;
}
wepN[i] = data.getItems().get(i).getName();
wepQty++;
}
Numerous ways:
String currentName;
for(i=0;i<100;++i) {
currentName=data.getItems().get(i).getName();
if(currentName == null || currentName.length() ==0) {
break;
}
// continue with old code here
}
If you don't like explicit breaks:
String currentName;
while(anyLeft) {
currentName=data.getItems().get(i).getName();
anyLeft= currentName != null && currentName.length() > 0;
if(anyLeft) {
// continue with old code here
}
}
why you need to use while here?
how about:
for (int i = 0; i < 100 && data.getItems().get(i).getName() != null; i++ {
wepN[i] = data.getItems().get(i).getName();
wepQty++;
}
or
int i = 0;
while (data.getItems().get(i).getName() != null && i < 100) {
wepN[i] = data.getItems().get(i).getName();
wepQty++;
i++
}
Something like this is what you are after:
Collection<String> original = new LinkedList<String>();
original.add("String1");
original.add("String2");
original.add("");
original.add(null);
original.add("String 3");
Collection<String> tested = new LinkedList<String>();
for(String string: original) {
if(null != string && !string.isEmpty()) {
tested.add(string);
}
}
String[] stringArray = tested.toArray(new String[tested.size()]);
I would argue not to use array at all and just stick to the Collection type however.
If you want to stop on the first occurance of a null or empty string just do:
if(null != string && !string.isEmpty()) {
tested.add(string);
} else {
break;
}
There are a few considerations depending on whether the original was a collection.
If you had an array Data[] data,
String[] dataCopy = new String[data.length];
int i = 0;
for (Data datum: data){
if (datum==null)break;
dataCopy[i++] = datum;
}
But that is not optimal because you would be assigning more array cells than necessary if the original data had 100 cells but the 50th cell is where the empty string is found.
Using an ArrayList would let the JVM manage the expansion of cells, so that at the end of it you just convert the ArrayList to an array using toArray(). It's not a conversion really, but toArray withdraws the internally managed array from the ArrayList.
ArrayList<String> dataList = new ArrayList<String>(data.length);
for (Data datum: data){
if (datum==null)break;
dataList.add(datum);
}
String[] dataCopy = {};
dataCopy = datalist.toArray(dataCopy);
Or if the array you are processing is a member of data:
ArrayList<String> dataList = new ArrayList<String>(data.length);
for (Data datum: data.getItems()){
String name = datum.getName();
if (name==null)break;
dataList.add(name);
}
String[] dataCopy = {};
dataCopy = datalist.toArray(dataCopy);
Or if the original data structure implements Iterable. Let's say the class of items is Item.
Iterator<Item> itemit = data.getItems().iterator();
ArrayList<String> dataList = new ArrayList<String>(data.length);
while(itemit.hasNext()){
String name = itemit.next().getName;
if (name==null)break;
dataList.add(name);
}
String[] dataCopy = {};
dataCopy = datalist.toArray(dataCopy);