Searching a multi-dimensional array in a menu page - java

I'm trying to create a menu page that allows addition to the array, output of the array and to search by name. I'm struggling with the search part, as it is a multi-dimensional array. How do I search just the names part of each object?
I'm also not sure how to loop this so that they return to the main page after each request, and therefore the array remains updated with any new editions.
package qa.com.task;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import qa.com.task.Person;
public class Runner {
public static void main(String[] args) {
Person pp1 = new Person("Karen", 27, "DevOps Engineer");
Person pp2 = new Person("Jim", 24, "Software Engineer");
// Create array
ArrayList<Person> people = new ArrayList<Person>();
people.add(pp1);
people.add(pp2);
// Search array
Scanner scan = new Scanner(System.in);
System.out.println("---------------------MENU---------------------");
System.out.println("------Create--------Search-------Output All---");
System.out.println("------type c--------type s---------type o-----");
String request = scan.nextLine();
if (request.contains("c")){
//CREATE NEW PERSON
System.out.println("----------Create Request: Enter Name----------");
String newname = scan.nextLine();
System.out.println("-------------------Enter Age-------------------");
Integer newage = scan.nextInt();
scan.nextLine();
System.out.println("-------------------Job Title-------------------");
String newjobtitle = scan.nextLine();
Person ppnew = new Person(newname, newage, newjobtitle);
people.add(ppnew);
System.out.println("-----Updated Array with New Creation Request----");
System.out.println(Arrays.toString(people.toArray()));
}
if (request.contains("s")){
//SEARCH
System.out.println("----------Search Request: Enter Name----------");
String searchname = scan.nextLine();
}
if (request.contains("o")){
//OUTPUT DATABASE
System.out.println("----------------Output Request:----------------");
System.out.println(Arrays.toString(people.toArray()));
}
}}

You can filter your people list based on a person name.
List<Person> filteredPeople = people.stream()
.filter(person -> person.getName().contains(searchname)) // Filter condition
.collect(Collectors.toList()); // Get the result as list
Then you can do what you want with filteredPeople.
Otherwise you can use a traditional for loop to iterate over the list and "print" Persons who match the condition, something like below.
List<Person> people...;
boolean stop = false;
while(!stop) {
// print menu (with exit command)
// handle commands and if exit command, set stop = true.
}

Related

If matched then add elements of ArrayList_A to ArrayList , if not then add elements of ArrayList_B to ArrayList

I have the following code:
package sportsCardsTracker;
import java.io.*;
import java.text.*;
import java.util.*;
import java.util.stream.Collectors;
public class Test_Mark6 {
public static ArrayList<String> listingNameList;
public static ArrayList<String> finalNamesList;
public static void main(String[] args) throws IOException, ParseException {
listingNameList = new ArrayList();
listingNameList.add("LeBron James 2017-18 Hoops Card");
listingNameList.add("Stephen Curry Auto Patch, HOT INVESTMENTS!");
listingNameList.add("Michael Jordan 1998 Jersey Worn Card");
ArrayList<String> playersNamesList = new ArrayList();
playersNamesList.add("LeBron James");
playersNamesList.add("Stephen Curry");
playersNamesList.add("Michael Jordan");
finalNamesList = new ArrayList();
String directory = System.getProperty("user.dir");
File file = new File(directory + "/src/sportsCardsTracker/CardPrices.csv");
FileWriter fw = new FileWriter(file, false); //true to not over ride
for (int i = 0; i < listingNameList.size(); i++) {
for (String listingNames : listingNameList) {
List<String> result = NBARostersScraper_Mark3.getNBARoster().stream().map(String::toLowerCase).collect(Collectors.toList());
boolean valueContained = result.stream().anyMatch(s -> listingNames.toLowerCase().matches(".*" + s + ".*"));
if(valueContained == true) {
finalNamesList.add(//The players' name);
}
}
fw.write(String.format("%s, %s\n", finalNamesList.get(i)));
}
}
}
Basically, in the listingsNameList, I have the listing's names and in the playersNamesList, I have all the players' names. What I would like is that, if the code matches the names between the two arrayList and find a player's name, it should returns the players' only.
For example, instead of "LeBron James 2017-18 Hoops Card" it should return "Lebron James" only. If it does not find anything, then just return the listing's name. So far, I have created a new ArrayList namely finalNamesList, my idea would be using an if statement (if match found then add players' name to finalNamesList, if not add the listing' name to finalNamesList). However the code above is not working and it is just adding all of the names in the listingNameList to the finalNamesList. I suspect that the way I grab the index is wrong - but I don't know how to fix it.
The method you are using to match a pattern that seems wrong. Instead of "match()" you can use string contains method as below.
List<String> temp = new ArrayList<>();
for (String listingNames : listingNameList) {
temp = playersNamesList.parallelStream().filter(s -> listingNames.toLowerCase().contains(s.toLowerCase())).map(s -> s).collect(Collectors.toList());
if(temp.size() > 0){
System.out.println(temp.get(0));
//fw.write(String.format("%s, %s\n", temp.get(0));
}
}
One more thing, You don't need to use 2 for loop here, with one loop you can achieve your output.
Though You can still optimize this code, I have taken the temp list above that you can avoid.

Returning ArrayList from HashMap

I have a program that adds the name of the donors as key in the HashMap with their Cities(ArrayList of city) as value. So, I have to take the name of the donor and first check whether this name is available in the map or not , if the name is available and the donor is donating from a different city then I need to update the cities arraylist in the map and if it is a new donor then I need to just add the donor in the map.
if anyone can help me with this problem, I have been facing great crisis because of this. Totally stucked.
I have attached my code.
import java.util.Scanner;
import java.util.ArrayList;
import java.util.HashMap;
public class MultCityMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
CollectionUtil cu = new CollectionUtil();
String donorName,city;
Scanner sc = new Scanner(System.in);
ArrayList<String> donorCity = new ArrayList<String>();
boolean choiceFlag = true;
while(choiceFlag){
System.out.println("Enter name");
donorName = sc.nextLine();
System.out.println("Enter city name");
city = sc.nextLine();
ArrayList<String> newCity = cu.nameKeyChecker(donorName,donorCity);
newCity.add(city);
cu.addDonor(donorName, newCity);
System.out.println("donate again? (1/0)");
int choice = sc.nextInt(); sc.nextLine();
if(choice == 1)
choiceFlag = true;
else
choiceFlag = false;
}
System.out.println(CollectionUtil.donorMap);
}
}
import java.util.ArrayList;
import java.util.HashMap;
public class CollectionUtil {
static HashMap<String, ArrayList<String>> donorMap = new HashMap<>();
public ArrayList<String> nameKeyChecker(String name, ArrayList<String> city){
if(donorMap.containsKey(name))
return (ArrayList<String>)donorMap.get(name);
else
donorMap.put(name, city);
return (ArrayList<String>)donorMap.get(name);
}
public void addDonor(String name, ArrayList<String> city){
donorMap.put(name, city);
}
}
You've made this way more complicated than it needs to be.
Given: Map<String, List<String>> donors; representing a donor's name with a list of cities donated to, all you need to add a new city is:
donors.computeIfAbsent(donorName, d -> new ArrayList<String>()).add(newCity);
This code will fetch the existing list, but, if there is no list, it 'computes' a value first (by making a new list). Then, that list is returned (be it the newly computed list, or the existing one); so you just add the new city to it.
Voila. you can get rid of half of your code now; you don't need the util class (in general, if you name a class 'util', rethink things), nameKeyChecker is not needed, you don't need the donorCity variable here either.
Definitely the code is much more complicated than it has to be. Perhaps, you need little more practice on programming.
However, if you want to fix you code all you need is addDonor method that looks something like following
public void addDonor(String name, String city) {
if (donorMap.containsKey(name)) {
donorMap.get(name).add(city);
} else {
ArrayList<String> newCity = new ArrayList<>();
newCity.add(city);
donorMap.put(name, newCity);
}
}
You can get rid of nameKeyChecker.

Java split and add elements into corrsponding data type arraylists

My problem is when a user enters text it should have two elements to split when using .split() however with the items it splits how do I put them into different lists so that I can use integer based list to make calculations.
e.g.
a user enters "skyrim , 100" the 'skyrim' entry is a string however with the number (integer) '100' I want to split it removing the comma and add it to a ArrayList for calculations and with other inputs added.
game name(String) , hours(integers) <- template
skyrim , 100
oblivion , 25
GTA V , 50
so the listed items above are user input with 2 arguments separated by a comma, which will be split, then I need to add them to different arraylists.
Scanner input = new Scanner(System.in);
Arraylist<String> game = new Arraylist<>();
Arraylist<Integer> hours = new Arraylist<>();
Arraylist<Object> allGameData = new Arraylist<>();
String gameEntry = input.nextLine().split(" , ");
allGameData.add(gameEntry);
foreach(object items : allGameData) {
System.out.println(items);
}
so from here I should have:
skyrim , 100 , oblivion, 25, GTAV , 50
How do i put the game names into the game list and the numbers into the hours list?
Well for starters, the class you should be using is ArrayList with a capital L. So you need to change:
Arraylist<String> game = new Arraylist<>();
Arraylist<Integer> hours = new Arraylist<>();
Arraylist<Object> allGameData = new Arraylist<>();
to this:
ArrayList<String> game = new ArrayList<>();
ArrayList<Integer> hours = new ArrayList<>();
ArrayList<Object> allGameData = new ArrayList<>();
After we have them initialized correctly we add to the ArrayList with #.add so in your case you would add to the game and hours list like:
game.add("some game");
hours.add(10);
When you split your input with input.nextLine().split(" , "); we are expecting a String array to be returned. Currently you are trying to set this to just a String instead of a String array.
while (true){
System.out.println("Enter \"game , hours\" or \"Quit\"");
String line = input.nextLine();
if (line.equals("Quit")) break;
allGameData.add(line);
String[] parsedData = line.split(" , ");
game.add(parsedData[0]);
hours.add(Integer.parseInt(parsedData[1]));
}
You can use Integer.parseInt(). The code you submitted looks pseudo-codey, but this is something like what You're going for:
String gameEntry = input.nextLine();
allGameData.add(gameEntry);
String[] splitGameEntry = input.nextLine().split(" , ");
game.add(splitGameEntry[0]);
hours.add(Integer.parseInt(splitGameEntry[1]));
I don't know exactly what you're trying to accomplish with this code, but you may want to organize the game/hours into a class that holds both values. Your code would then look something like this:
public class GameInfo
{
private String name;
private int hours;
public GameInfo(String name, int hours)
{
this.name = name;
this.hours = hours;
}
[getters/setters]
#Override
public String toString()
{
return name + ": " + hours + " hours played!";
}
}
public class Main
{
public void doSomething()
{
Scanner input = new Scanner(System.in);
List<GameInfo> gameInfo = new ArrayList<>();
String[] gameEntry = input.nextLint().split(" , ");
gameInfo.add(new GameInfo(gameEntry[0], Integer.parseInt(gameEntry[1]));
for(GameInfo gameInfoPiece : gameInfo)
{
System.out.println(gameInfoPiece);
}
}
}
Using this approach, you would be able to add as much information into the GameInfo class as you want. For instance, if you wanted to change hours to expectedHoursToComplete and add actualHoursToComplete, you could easily do that.
You may find it easier if you rethink your approach. Rather than have 3 separate lists why not store it all in a single Map<String,Integer> where the key is the game name and the value is the number of hours.
Your code would look something like the following:
Scanner scan = new Scanner(System.in);
Map<String, Integer> gameHoursMap = new HashMap<>();
String currentValue = scan.nextLine();
// Loop until you meet some criteria to end such as typing q or quit
while(!currentValue.equalsIgnoreCase("q")){
// You would need to handle when the value of currentValue doesn't fit what you would normally be expecting before doing the rest
String[] vals = currentValue.split(",");
// Call trim method on the String incase there is any lingering whitespace
gameHoursMap.put(vals[0].trim(), Integer.valueOf(vals[1].trim()));
currentValue = scan.nextLine();
}
You would obviously need to write some error handling for when the input doesn't fit with what you're expecting but you get the gist.
UPDATE:
If you wanted to have more complicated info stored for each game you could wrap it up in a custom class GameInfo and then have a Map<String,GameInfo> where the key is the name and the value is the GameInfo. This would allow you to retrieve all of the game info for a game just based on the name.
public class GameInfo {
private String name;
private int hoursPlayed;
private int level;
// etc
}
You would then amend the while loop to create the GameInfo object instead of just putting a String and int into the Map
// Create the GameInfo object from the corresponding input supplied by the user
GameInfo game = new GameInfo(vals[0].trim(), Integer.valueOf(vals[1].trim()), Integer.valueOf(vals[2].trim()));
// Put it in the map with the name as the key
gameMap.put(game.getName(), game);

Hashtag Multiple

I am trying to find the number of unique hashtags in a tweet inputted by a user. for example, if someone inputs "#one #seven #one purple green #red", it would show 3 unique hashtags that would be "#one, #seven, #red". In my code, I can do that to one tweet, but I cannot figure out how to input multiple tweets and find all the unique hashtags from them.
package edu.bsu.cs121.jmgibson;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Tweet {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Please enter a tweet");
String tweet = scanner.nextLine();
Set<String> hashtags = getHashtags(tweet);
System.out.println(hashtags.toString());
}
public static Set<String> getHashtags(String tweet) {
String[] words = tweet.split(" ");
Set<String> hashtags = new HashSet<String>();
for (String word : words) {
if (word.startsWith("#")) {
hashtags.add(word);
}
}
return hashtags;
}
}
I don't want to do your homework for you, but I'll offer some suggestions:
In main(), you'll need a loop that asks for input and makes calls
to getHashtags().
Instead of creating a new HashSet inside of getHashtags(),
create one in main() (outside of the loop), and pass it in.
1.loop and get many tweet inputs
something like
for(int i=0;i<100;i++)
{
System.out.println("Please enter a tweet");
String tweet[i] = scanner.nextLine();
}
2.pass the tweetstring array instead of passing tweet string
3.loop through tweet array line by line and add tag if and only if not already added
public static Set<String> getHashtags(String[] tweet) {
Set<String> hashtags = new HashSet<String>();
//loop of tweet array starts
String[] words = tweet[i].split(" ");//i is loop variable
for (String word : words) {
if (word.startsWith("#")) {
//here add condition to check if hashings already doesnt have the word
hashtags.add(word);
}
}
}
//loop ends
return hashtags;
You need a loop in your main to gather multiple inputs.
I would gather your inputs into one string in order to work with your already defined getHashtags.
Something like this...
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Please enter a tweet");
String tweet = "";
while(!scanner.nextLine().equals("stop")){
tweet += scanner.nextLine();
}
Set<String> hashtags = getHashtags(tweet);
System.out.println(hashtags.toString());
}
So a loop and a += should do the trick.

Iterating through an array List and creating new ArrayLists when values are different, is this even possible?

I am fairly new to Java and I have stumbled across a problem I cannot figure out for the life of me. First let me explain what I am trying to do then I will show you the code I have so far.
I have a webservice that returns an array of arrays(which include company and lines of business strings). I wish to transform this into a string list, which I did in the first line of code below. Then I wish to Iterate through the list and every I come across a different value for company, I want to create a new ArrayList and add the associated line of business to the new list. Example output of webservice: 80,80,64,64 (this is presorted so the same companies will always be grouped together) the associated lobs would be 1,2,3,4 respectively. What I want: arraylist[0]: 1,2 arrayList[1]: 3,4
What I have so far:
List coList = Arrays.asList(coArray);
//create list of lists
List<List<String>> listOfLists = new ArrayList<List<String>>();
String cmp = "";
for (int i=0;i<coList.size();i++){//loop over coList and find diff in companies
String currentCo = ((__LOBList)coList.get(i)).getCompany();
String currentLob = ((__LOBList)coList.get(i)).getLobNum();
if(i<coArray.length-1){
String nextCo = ((__LOBList)coList.get(i+1)).getCompany();
if((currentCo.equals(nextCo))){
//do nothing companies are equal
}else{
log("NOT EQUAL"); //insert logic to create a new array??
ArrayList<String> newList = new ArrayList<String>();
// for(int j=0;j<coList.size();j++){
newList.add( ((__LOBList)coList.get(i)).getLobNum());
// }
for(int k=0; k<listOfLists.size();k++){//loop over all lists
for(int l=0;l<listOfLists.get(k).size();l++){ //get first list and loop through
}
listOfLists.add(newList);
}
}
}
}
My problem here is that it is not adding the elements to the new string array. It does correctly loop through coList and I put a log where the companies are not equal so I do know where I need to create a new arrayList but I cannot get it to work for the life of me, please help!
Yes you can do this but it's really annoying to write in Java. Note: This is a brain dead simple in a functional programming language like Clojure or Haskell. It's simply a function called group-by. In java, here's how I'd do this:
Initialize a List of Lists.
Create a last pointer that is a List. This holds the last list you've added to.
Iterate the raw data and populate into the last as long as "nothing's changed". If something has changed, create a new last.
I'll show you how:
package com.sandbox;
import java.util.ArrayList;
import java.util.List;
public class Sandbox {
public static void main(String[] args) {
ArrayList<String> rawInput = new ArrayList<String>();
rawInput.add("80");
rawInput.add("80");
rawInput.add("60");
rawInput.add("60");
new Sandbox().groupBy(rawInput);
}
public void groupBy(List<String> rawInput) {
List<List<String>> output = new ArrayList<>();
List<String> last = null;
for (String field : rawInput) {
if (last == null || !last.get(0).equals(field)) {
last = new ArrayList<String>();
last.add(field);
output.add(last);
} else {
last.add(field);
}
}
for (List<String> strings : output) {
System.out.println(strings);
}
}
}
This outputs:
[80, 80]
[60, 60]
Of course, you can do what the other guys are suggesting but this changes your data type. They're suggesting "the right tool for the job", but they're not mentioning guava's Multimap. This will make your life way easier if you decide to change your data type to a map.
Here's an example of how to use it from this article:
public class MutliMapTest {
public static void main(String... args) {
Multimap<String, String> myMultimap = ArrayListMultimap.create();
// Adding some key/value
myMultimap.put("Fruits", "Bannana");
myMultimap.put("Fruits", "Apple");
myMultimap.put("Fruits", "Pear");
myMultimap.put("Vegetables", "Carrot");
// Getting the size
int size = myMultimap.size();
System.out.println(size); // 4
// Getting values
Collection<string> fruits = myMultimap.get("Fruits");
System.out.println(fruits); // [Bannana, Apple, Pear]
Collection<string> vegetables = myMultimap.get("Vegetables");
System.out.println(vegetables); // [Carrot]
// Iterating over entire Mutlimap
for(String value : myMultimap.values()) {
System.out.println(value);
}
// Removing a single value
myMultimap.remove("Fruits","Pear");
System.out.println(myMultimap.get("Fruits")); // [Bannana, Pear]
// Remove all values for a key
myMultimap.removeAll("Fruits");
System.out.println(myMultimap.get("Fruits")); // [] (Empty Collection!)
}
}
It sounds to me like a better choice would be a Map of Lists. Let the company ID be the key in the Map and append each new item for that company ID to the List that's the value.
Use the right tool for the job. Arrays are too low level.
Create a Map<String, List<Bussiness>>
Each time you retrieve a company name, first check if the key is already in the map. If it is, retrieve the list and add the Bussiness object to it. If it is not, insert the new value when a empty List and insert the value being evaluated.
try to use foreach instead of for
just like
foreach(List firstGroup in listOfLists)
foreach(String s in firstGroup)
............
Thanks for the input everyone!
I ended up going with a list of lists:
import java.util.*;
import search.LOBList;
public class arraySearch {
/**
* #param args
*/
public static void main(String[] args) {
LOBList test = new LOBList();
test.setCompany("80");
test.setLOB("106");
LOBList test1 = new LOBList();
test1.setCompany("80");
test1.setLOB("601");
LOBList test2 = new LOBList();
test2.setCompany("80");
test2.setLOB("602");
LOBList test3 = new LOBList();
test3.setCompany("90");
test3.setLOB("102");
LOBList test4 = new LOBList();
test4.setCompany("90");
test4.setLOB("102");
LOBList test5 = new LOBList();
test5.setCompany("100");
test5.setLOB("102");
LOBList BREAK = new LOBList();
BREAK.setCompany("BREAK");
BREAK.setLOB("BREAK");
BREAK.setcompany_lob("BREAK");
// create arraylist
ArrayList<LOBList> arlst=new ArrayList<LOBList>();
// populate the list
arlst.add(0,test);
arlst.add(1,test1);
arlst.add(2,test2);
arlst.add(3,test3);
arlst.add(4,test4);
arlst.add(5,test5);
//declare variables
int idx = 0;
String nextVal = "";
//loops through list returned from service, inserts 'BREAK' between different groups of companies
for(idx=0;idx<arlst.size();idx++){
String current = arlst.get(idx).getCompany();
if(idx != arlst.size()-1){
String next = arlst.get(idx+1).getCompany();
nextVal = next;
if(!(current.equals(next))){
arlst.add(idx+1,BREAK);
idx++;
}
}
}
//add last break at end of arrayList
arlst.add(arlst.size(),BREAK);
for(int i=0;i<arlst.size();i++){
System.out.println("co:" + arlst.get(i).getCompany());
}
//master array list
ArrayList<ArrayList<LOBList>> mymasterList=new ArrayList<ArrayList<LOBList>>();
mymasterList = searchListCreateNewLists(arlst);
//print log, prints all elements in all arrays
for(int i=0;i<mymasterList.size();i++){
for(int j=0;j<mymasterList.get(i).size();j++){
System.out.println("search method: " + mymasterList.get(i).get(j).getCompany());
}
System.out.println("end of current list");
}
}
//method to loop over company array, finds break, creates new array list for each company group,
//adds this to a list of lists(masterList)
public static ArrayList<ArrayList<LOBList>> searchListCreateNewLists(ArrayList<LOBList> list){
ArrayList<ArrayList<LOBList>> masterList=new ArrayList<ArrayList<LOBList>>();
int end = 0;
int start = 0;
int index = 0;
for(int i=0;i<list.size();i++){
if(list.get(i).getCompany().equals("BREAK")){
end = i;//end is current index
masterList.add(new ArrayList<LOBList>());
for(int j = start;j<end;j++){
masterList.get(index).add(list.get(j));
}
index++;
start = i+1;
}
}
return masterList;
}
}
The output is:
search method: 80
search method: 80
search method: 80
end of current list
search method: 90
search method: 90
end of current list
search method: 100
end of current list
So all company LOBList objects with Company: 80, are grouped together in a list, as are 90 and 100.
To iterate through the list you can use
ListIterator litr = coList.listIterator();
while(litr.hasNext()){
}

Categories