I'm lacking the knowledge on 2d arrays and I need help populating data from an array into a few class variables.
So I have simple product class that looks like this:
public class Product{
int prodID;
String prodName;
Double prodCost;
int prodQuantity;
I also have a class with two methods:
Taking a CSV and converting it to an array - done
Taking variables from the array and adding them to the appropriate variables - not finished
The array/CSV looks like this:
product ID | product name | product cost | quantity
-----001----- | -----item1----- | -----5.99----- | -----3-----
-----002----- | -----item2----- | -----2.99----- | -----5-----
I want to write code that iterates over the array, and creates Product instances for each line. Eventually I will have a list of products. I can always assume the CSV is in fixed format so there will always only be 4 variables as seen in the table above.
So this is what I have so far:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class productsImport extends Product {
public static List<List<String>> csvToArray() {
String fileName = "c:\\temp\\test.csv";
File file = new File(fileName);
// this gives you a 2-dimensional array of strings
List<List<String>> lines = new ArrayList<>();
Scanner inputStream;
try {
inputStream = new Scanner(file);
while (inputStream.hasNext()) {
String line = inputStream.next();
String[] values = line.split(",");
// this adds the currently parsed line to the 2-dimensional string array
lines.add(Arrays.asList(values));
}
inputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return lines;
}
public static void mapToProdcut(List<List<String>> lines){
for (List<String> line : lines) {
Product p = new Product();
for (String value : line) {
???
}
}
}
public static void main(String[] args) {
csvToArray();
mapToProdcut(csvToArray());
}
}
The first method converts the CSV to an array. The second method is where I'm stuck. I don't know how to iterate properly over the array to make sure that p.prodID, p.prodName, p.prodCost and p.prodQuantity are all populated with the corresponding column. I want to skip over the first row, because it will always show the field titles and they're not relevant.
Any help with this would be great :)
First thing to do is to create a constructor that takes all variables as parameters to simplify the code
public Product(int prodID, String prodName, Double prodCost, int prodQuantity) {
this.prodID = prodID;
this.prodName = prodName;
this.prodCost = prodCost;
this.prodQuantity = prodQuantity;
}
If you are running Java 8 you can use streams
List<Product> products =
lines.stream()
.skip(1)
.map(s -> new Product(
Integer.valueOf(s.get(0)),
s.get(1),
Double.valueOf(s.get(2)), Integer.valueOf(s.get(3))
)).collect(Collectors.toList());
Otherwise you can use a for loop
List<Product> products = new ArrayList<>();
for (int i = 1; i < lines.size(); i++) {
List<String> s = lines.get(i);
Product product = new Product(
Integer.valueOf(s.get(0)),
s.get(1),
Double.valueOf(s.get(2)),
Integer.valueOf(s.get(3)));
products.add(product);
}
Related
I'm working with a large set of imported data and retrieving certain parts of it in the main method with 2 classes(WeatherStation, WeatherReading).The data is temperature readings at loads of weather stations(station id, name, lat, lon, year, time, temp etc) I made a third class (SoloSiteIds) whose sole purpose was to return a whole and complete ArrayList of the site ids with no duplication. But I cannot import the ArrayList from the other class into my main method. My SoloSiteIds class looks like this:
public class SoloSiteIds {
static ArrayList <Integer> siteIds = new ArrayList <Integer>();
public SoloSiteIds() {
}
public SoloSiteIds( ArrayList <Integer> siteIds) {
String[] weatherData = WeatherData.getData();{ // get the weather data
for (int i = 1; i < weatherData.length; i++) {
String line = weatherData[i];
String[] elements = line.split(","); // Split the data at ",
String siteid = elements[0]; // convert all the site id's at index 0 to integers
int id = Integer.parseInt(siteid);
if(!siteIds.contains(id)) {
siteIds.add(id);
}
this.siteIds=siteIds;
}
}
}
public static ArrayList<Integer> getSiteIds() {
return siteIds;
}
public ArrayList<Integer> setSiteIds(ArrayList<Integer> siteIds) {
return this.siteIds = siteIds;
}
}
The main method where I am trying to import the ArrayList "siteIds" looks like this:
WeatherStation thisStation = new WeatherStation (id, name, lat, lon);
WeatherReading thisReading = new WeatherReading(year, month, date, hour, windSpeed, temp);
SoloSiteIds siteList= new SoloSiteIds();
String[] weatherData = WeatherData.getData();{ // get the weather data
for (int i = 1; i < weatherData.length; i++) {
String line = weatherData[i];
String[] elements = line.split(","); // Split the data at ","
String siteid = elements[0]; // convert all the site id's at index 0 to integers
id = Integer.parseInt(siteid);
thisStation.setId(id);
thisStation.setName(elements[1]);
//parse the different elements into different data types
String stringLat = elements[2];
lat= Double.parseDouble(stringLat);
lat = thisStation.setLat(lat);
lat=thisStation.setLat(lat);
String stringLon = elements[3];
lon= Double.parseDouble(stringLon);
lat = thisStation.setLon(lon);
lat=thisStation.setLon(lon);
String stringTemp=elements[9];
temp=Double.parseDouble(stringTemp);
temp=thisReading.setTemp(temp);
Only the top part is relevant. I have tried lots of different variation of .set and .get using "thisList" instance and a new ArrayList like
ArrayList<Integer> siteIds = thisList.setSiteIds();
ArrayList<Integer> siteIds= SoloSiteIds.getSiteIds();
thisList=Siteids.setSiteIds();
thisList=SingleSoloSites.setSiteIds();
etc etc. This might look stupid but im just showing Ive tried numerous things and i am stuck
Thanks
I believe your problem is that you are initializing siteIds as an empty Arry list but you are not setting the data in a static way (the set Method is not static).
As far as I am aware of your situation, I belive that the SoloSiteIds class is unnescessary. I would solve your problem with an ArrayList declared in your main class and initialize with a getSoleIds() method also declared in your main class.
The getSoleIds() Method should contain the code currently in the SoleSiteIds initializer.
I am working on the first part of a String permutation problem and I am just looping over the first char of a string and swap it with every following char of that same String. I initialized an empty ArrayList to store all of those permutations called listeFinale. When I am printing that ArrayList, I am getting a collection of object and not values ([[C#61bbe9ba, [C#61bbe9ba, [C#61bbe9ba, [C#61bbe9ba]), how can I print each char stored in the ArrayList?
import java.util.ArrayList;
import java.util.List;
public class checkPermu {
public static void main(String[] args) {
String myString = "aabc";
applyPermu(myString);
}
public static void applyPermu(String toCheck){
char[] newString = toCheck.toCharArray();
List listeFinale = new ArrayList();
for(int i = 0 ; i < newString.length ; i ++){
char temp = newString[0];
newString[0] = newString[i];
newString[i] = temp;
listeFinale.add(newString);
System.out.println(listeFinale);
}
}
}
First of all, don't use raw types for your List please.. Change:
List listeFinale = new ArrayList();
to:
List<char[]> listeFinale = new ArrayList<>();
As for your actual problem. Those values you see are the default toString() outputs of your inner character-arrays. You could iterate over your list, and call the java.util.Arrays.toString(char[]) method for them like this:
listeFinale.forEach(arr -> System.out.println(Arrays.toString(arr)));
Or, if you want to print them back as String again, use new String(char[]):
listeFinale.forEach(arr -> System.out.println(new String(arr)));
Try it online.
so I am working on this small project to build an index for 1400 files corpus then searching for keywords using the index. the index should have the frequency of the keyword and its position "file name". Output should be top ten relevant docs according to frequency of the keyword in each.
for Example:
flower text1.txt 3
flower text2.txt 2
.
.
this is what I have so far and I'm having difficulty with the tuple as I want to add 3 values to the hashmap
import java.io.*;
import java.nio.charset.*;
import java.nio.file.*;
import java.util.*;
public class MyIndex {
static Map<String, Tuple<Integer, String>> map = new HashMap();
static String readFile(String path, Charset encoding) throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
public static void main (String [] args) throws IOException {
File myDirectory = new File(
"/Users/.../processedFiles");
File[] fileList = myDirectory.listFiles();
for(int i = 1;i<fileList.length;i++) {
Scanner scan = new Scanner (new File(fileList[i].getPath()));
while(scan.hasNextLine()) {
String line = scan.nextLine();
map.put(line, new Tuple (1,fileList[i].getName())); //tuple is frequency of word and file name
}
}
}
public class Tuple<X, Y> {
public final X x;
public final Y y;
public Tuple(X x, Y y) {
this.x = x;
this.y = y;
}
}
}
the error is in put(...)
I didn't add the frequency method yet and this is what I have so far
static void frequency(String [] array) {
Map<String, Integer> map = new HashMap<String, Integer>();
for (String string : array) {
int count = 0;
if (!map.containsKey(string)) {
map.put(string, 1);
}
else {
count = map.get(string);
map.put(string, count + 1);
}
}
is there a better way to do this from scratch as we cannot use lucene etc..
how to put it all together to read and index 1400 files using the Tuple class?
I am open to any suggestions
thanks
I want to add 3 values to the hashmap
Your map's definition only stores 1 tuple per string. I suggest letting the second parameter be an Arraylist of Tuples. (P.S. The Pair class exists so you don't have to create a Tuple class). This will transform your map from what you asked for:
flower text1.txt 3, flower text2.txt 2
into
flower text1.txt 3, text2.txt 2
where the key is "flower" and the val is an Arraylist with position 0 = Tuple(3, text1.txt), and position 1 = Tuple(2, text2.txt). You can refer to the code below.
Arraylist<Tuple> A = map.get("flower")
System.out.println(A.get(0).y + " " + A.get(0).x)
System.out.println(A.get(1).y + " " + A.get(1).x)
I'm not sure why there's a need for your frequency method since you can update the frequency while you read the files. Because this sounds like your assignment, I won't give you all the details but point you in the right direction:
while(scan.hasNextLine()) {
//Read all the words in the line and update their count in the map while being aware of the name of the file you're currently reading.
}
There are still things you need to figure out but I hope I helped.
My problem is that I created an array from a csv file and I now have to output any values with duplicates.
The file has a layout of 5x9952. It consists of the data:
id,birthday,name,sex, first name
I'd now like the program to show me in each column (e.g. name) which duplicates there are. Like if there are two people which the same name. But whatever I try from what I found on the Internet only shows me the duplicates of rows (like if name and first name are the same).
Here's what I got so far:
package javacvs;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
*
* #author Tobias
*/
public class main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
String csvFile = "/Users/Tobias/Desktop/PatDaten/123.csv";
String line = "";
String cvsSplitBy = ",";
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
while ((line = br.readLine()) != null) {
// use comma as separator
String[] patDaten = line.split(cvsSplitBy);
for (int i = 0; i < patDaten.length-1; i++)
{
for (int j = i+1; j < patDaten.length; j++)
{
if( (patDaten[i].equals(patDaten[j])) && (i != j) )
{
System.out.println("Duplicate Element is : "+patDaten[j]);
}
}
}
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
(I changed the name of the csv as it contains confidential data)
The real thing here: stop thinking "low level". Good OOP is about creating helpful abstractions.
In other words: your first stop should be to create a meaningful class definition that represents the content of one row, lets call it the Person class for now. And then you separate your further concerns:
you create one class/method that does nothing else but reading that CSV file - and creating one Person object per row
you create a meaningful data structure that tells you about duplicates
The later could (for example) some kind of reverse indexing. Meaning: you have a Map<String, List<Person>>. And after you have read all your Person objects (maybe in a simple list), you can do this:
Map<String, List<Person>> personsByName = new HashMap<>();
for (Person p : persons) {
List<Person> personsForName = personsByName.get(p.getName());
if (personsByName == null) {
personsForName = new ArrayList<>();
personsByName.put(p.getName(), personsForName);
}
personsForName.add(p);
}
After that loop that map contains all names used in your table - and for each name you have a list of the corresponding persons.
You are iterating upon the rows instead of iterating upon the column. What you need to do is to have the same cycle but upon the column.
What you can do is to acumulate the names in a separate array and than iterate it. I am sure you know what index is the column you want to compare. So you will need one cycle extra to accumulate the column you want to check for duplications.
It's a bit unclear what you want presented, the whole record, or only that there are duplicate names.
For the name only:
String csvFile = "test.csv";
List<String> readAllLines = Files.readAllLines(Paths.get(csvFile));
Set<String> names = new HashSet<>();
readAllLines.stream().map(s -> s.split(",")[2]).forEach(name -> {
if (!names.add(name)) {
System.out.println("Duplicate name: " + name);
}
});
For the whole record:
String csvFile = "test.csv";
List<String> readAllLines = Files.readAllLines(Paths.get(csvFile));
Set<String> names = new HashSet<>();
readAllLines.stream().forEach(record -> {
String name = record.split(",")[2];
if (!names.add(name)) {
System.out.println("Duplicate name: " + name + " with record " + record);
}
});
Your problem is the nesting of your loops. What you do is, that you read one line, split it up and then you compare the fields of this one row with each other. You do not even compare one line with other lines!
So first you need an array for all lines so you can compare these lines. As GhostCat recommended in his answer you should use your own class Person which has the five fields as attributes. But you could use a second array, so you can work with the indexes as Alexander Petrov said in his answer. In the latter case, you get a two-dimensional array:
String[][] patDaten;
After that you read all lines of your csv-file and for each line you create a new Person or a new inner array.
After reading the entire file, you compare the fields as you want. Here you use your double loop. So you compare patDaten[i].getName() with patDaten[j].getName() or with the array patDaten[i][1] with patDaten[j][1].
i have an assignment for school and this is what i have so far with notes of what i'm trying to do
import java.io.*;
import java.util.Scanner;
public class UniquesDupesTester
{
public static void main( String args[] ) throws IOException
{
// make a Scanner and associate it with "UniquesDupes.dat"
// as long as there are Strings in the file
// read in a String,
// create a UniquesDupes object with it
// print the object
Scanner in = new Scanner(new File("UniquesDupes.dat"));
while (in.hasNextLine())
{
String n = in.nextLine();
UniquesDupes a = new UniquesDupes(n);
a.getUniques();
a.getDupes();
System.out.println (a);
}
}
}
seperate file
import java.util.Set;
import java.util.TreeSet;
import java.util.Arrays;
import java.util.ArrayList;
public class UniquesDupes
{
private ArrayList<String> list;
/**
* constructs a UniquesDupes object such that list contains the space delimited strings
* parsed from input
* #param input a String containing the list of words separated by spaces
*/
public UniquesDupes(String input)
{
list = new ArrayList<String>();
String[] words = "abc cde fgh ijk".split(" ");
ArrayList<String> list = new ArrayList<String>(Arrays.asList(words));
}
/**
* returns a set of Strings containing each unique entry in the list
*/
public Set<String> getUniques()
{
Set<String> uniques = new TreeSet<String>();
for(String a:list)
{
uniques.add(a);
}
return uniques;
}
/**
* returns a set of Strings containing each entry in the list that occurs more than once
*/
public Set<String> getDupes()
{
Set<String> uniques = new TreeSet<String>();
Set<String> dupes = new TreeSet<String>();
for(String a:list)
{
uniques.add(a);
{
if(uniques.add(a) == false)
{
dupes.add(a);
}
}
}
return dupes;
}
/**
* returns the original list, the list of duplicates and the list of uniques
* #return the String version of the object
*/
public String toString()
{
return "Orig list :: " + list
+ "\nDuplicates :: " + getDupes()
+ "\nUniques :: " + getUniques() + "\n\n";
}
}
here is the dat file if you need it
a b c d e f g h a b c d e f g h i j k
one two three one two three six seven one two
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 6
it compiles and runs but all the files return blank i have no idea what i did wrong help or hints would be appreicated
The logic is almost correct.
The UniquesDupes class is almost OK, but the constructor is not OK. It should just be
public UniquesDupes() // no args, default constructor
{
list = new ArrayList<String>(); //just initialize the list
}
At the same time, said class would need an addString method:
public void addString(String input) {
String[] words = input.trim().split(" "); //split the input string into words by spaces, after trimming whitespace
this.list.addAll(Arrays.asList(words)); //adding them to the list.
}
The while loop should be changed a bit. You want only 1 instance of the UniquesDupes class, and then add each line using the addString method created before.
UniquesDupes a = new UniquesDupes(); //create it here
while (in.hasNextLine())
{
String n = in.nextLine();
a.addString(n); //adding the string
}
Then the results need to be handled differently
Collection<String> uniques = a.getUniques();
Collection<String> dupes = a.getDupes();
System.out.println (uniques.toString());
System.out.println (dupes.toString());
That said, the logic was almost right...
An ugly thing you did is however this part:
list = new ArrayList<String>(); //using instance variable
String[] words = "abc cde fgh ijk".split(" ");
ArrayList<String> list = new ArrayList<String>(Arrays.asList(words));
// ^^ declaring local variable the same name as the instance variable
This is bad. You shouldn't do it. No-no. Don't do it again! Picking up this habit makes code exceptionally hard to read, and crazy insane to maintain...