Hey this code works just fine, but it is difficult to read. I am looking for a way to do this better.
public void printArray(String[/*row*/][/*column*/] twoDiArray) {
if (twoDiArray.length == 2) {
for (int i = 0; i < twoDiArray[0].length; i++) {
//prints attribute name and value
attributeNameAndValue(twoDiArray[0][i],twoDiArray[1][i]);
}
} else {
System.out.println("Does not fit format standards :: 2d array :: two rows max :: first row name :: second row value");
}
}
The part I seriously dislike is the length calls in the if statement and the for loop. Is there a better way to do this or is it just a sloppy section of java language.
You have pairs name-value, if your names are unique, you should use Map<String, Integer> instead. Otherwise, create your own class called e.g. Attribute and use List<Attribute>:
public class Attribute {
private final String name;
private final int value;
public Attribute(String name, int value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public int getValue() {
return value;
}
}
This gives you compile-time safety for the second dimension. Your code would look like this:
public void printArray(List<Attribute> attributes) {
for (Attribute attribute : attributes) {
attributeNameAndValue(attribute.getName(), attribute.getValue());
}
}
You can use new variable to save the value of twoDiArray.length and use new var below.
This can certainly be cleaned up a little bit. A different approach as other people have mentioned would have much neater code. It's a little bizarre that you have row and column like that. Reversing the order would also make things cleaner:
public void printArray(String[/*row*/][/*column*/] twoDiArray){
if(twoDiArray.length!=2){
System.out.println("Does not fit format standards :: 2d array :: two rows max :: first row name :: second row value");
return;
}
int len = twoDiArray[0].length;
for(int i = 0; i<len.length; i++){
//prints attribute name then value
attributeNameAndValue(twoDiArray[0][i],twoDiArray[1][i]);
}
}
Another thing would be to change attributeNameAndValue to accept i and twoDiArray for a "neater" call.
another way to check array
public void printArray(String[/*row*/][/*column*/] twoDiArray){
assert twoDiArray.length == 2;
for(int i=0; i<twoDiArray[0].length; i++){
attributeNameAndValue(kvp[i][0], kvp[i][1]);
}
}
To improve the code readability apply the java code conventions (http://www.oracle.com/technetwork/java/codeconvtoc-136057.html).
Introduce variables rows and columns (for the number of rows and number of columns)
public void printArray(String[/*row*/][/*column*/] twoDiArray) {
int rows = twoDiArray.length;
if (rows != 2) {
System.out.println("Does not fit format standards :: 2d array :: two rows max :: first row name :: second row value");
return;
}
int columns = twoDiArray[0].length;
for (int column = 0; column < columns; column++) {
//prints attribute name then value
attributeNameAndValue(twoDiArray[0][column], twoDiArray[1][column]);
}
}
Related
we have sequence of 4 characters (A,B,C and D)that map to numbers form 1 to n.
we define components to be:
Component(k) :
A {cell[k]}
if Color(left_k) = Color(k)
then
A <-- A U Component(left_k)
if Color(right_k) = Color(k)
then
A <-- A U Component(left_k)
return A
there is 3 types of operations(the numbers in list indicate the input):
by giving index it should remove the component in that index(the numbers mapping to characters are fixed)
example : AABBBDA is the string. if index is 3 it should return AADA
by giving index it should rotate the string based on the component on that index(the numbers mapping to characters are fixed)
example : AABBBDA is the string. if index is 3 it should return DABBBAA
it should print the string.
inputs are like:
1 2 --> first operation with index=2
2 3 --> second operation with index=3
3 --> third operation
It's an assignment, happy to get help.
this is what i've tried so far:
public static void main(String[] args)
{
int numberOfOps;
String[] print = new String[30];
List list = new List();
Scanner input = new Scanner(System.in);
int count = input.nextInt();
String colors = new String();
colors = input.next();
for(int i = 0; i < count; i++)
{
list.add(colors.charAt(i));
}
numberOfOps = input.nextInt();
list.printElement();
for (int i = 0; i < numberOfOps; i++)
{
int op = input.nextInt();
if(op == 1)
{
int index = input.nextInt();
char c = list.item[index];
int temp = index;
int prevIndex = index;
int nexIndex = index;
if(index != 0)
{
while (list.item[--index] == c)
{
prevIndex--;
}
while (list.item[++temp] == c)
{
nexIndex++;
}
list.setNext(prevIndex-1, nexIndex+1);
}
else
{
while (list.item[++temp] == c)
{
nexIndex++;
}
list.setNext(prevIndex, nexIndex+1);
}
}
if(op == 2)
{
int index = input.nextInt();
}
if(op == 3)
{
print[i] = list.printElement();
}
}
}
here is my List class:
public class List {
// reference to linked list of items
public static final int MAX_LIST = 20;
public static final int NULL = -1;
public char item[] = new char[MAX_LIST]; // data
public int avail;
public int next[] = new int[MAX_LIST]; // pointer to next item
private int numItems; // number of items in list
public List()
{
int index;
for (index = 0; index < MAX_LIST-1; index++)
next[index] = index + 1;
next[MAX_LIST-1] = NULL;
numItems = 0;
avail = 0;
} // end default constructor
public void add(char e)
{
item[avail] = e;
avail = next[avail];
numItems++;
}
public String printElement()
{
String temp = null;
int index = 0;
while(index<avail)
{
temp += item[index];
System.out.println(item[index]);
index = next[index];
}
return temp;
}
public int size()
{
return numItems;
}
public void setNext(int i, int value)
{
next[i] = value;
}
}
if you test it you'll get, it has lots of problems, such as, I have no idea to do the rotate operation, and it has problem with connecting two components when the middle component has been removed.
This is a difficult question to answer, because the requirements are not properly stated.
For example the first bunch of pseudo-code does not make it clear whether A is a set, a multi-set or a list. The notation (use of curly brackets, and U (union?)) seems to say set ... but the output seems to be a list. Or maybe it is supposed to be a schema for a data structure??
And even the inputs are not clearly described.
But putting that on one side, there is still room for some (hopefully) helpful advice.
Make sure that >>you<< understand the requirements. (I imagine that the real requirements for the assignment are better stated than this, and the details have been "lost in translation".)
I would actually use an array list (or a StringBuilder) rather than a linked list for this. (But a properly implemented linked list ... implementing the List API ... would work.)
But whatever data structure you chose, there is no point in implementing it from scratch ... unless you are specifically required to do that. There are perfectly good list classes in the Java standard libraries. You should reuse them ... rather than attempting to reinvent the wheel (and doing a bad job).
If you are required to implement your own data structure type, then your current attempt is a mess. It looks like a hybrid between an array list and a linked list ... and doesn't succeed in being either. (For example, a decent array list implementation does not need a MAX_LIST, and doesn't have next pointers / indexes. And a linked list does not have any arrays inside it.)
This method should return the index of the first string that starts with the target.
Return -1 if no string starts with the target.
My implementations works but not covers all variations.
Code:
public int getIndex(ArrayList<String> text, String target)
{
int i = 0;
int index = -1;
boolean found = false;
while (!found && i < text.size()) //supply condition
{
for (String s : text) {
if (s.contains(target)) {
found = true;
} else {
i++;
}
if (found) index = i;
}
}
return index;
}
testing part:
public static void main(String[] args)
{
ArrayList<String> cities = new ArrayList<String>();
cities.add("Chicago");
cities.add("Houston");
cities.add("San Jose");
cities.add("Seattle");
cities.add("Denver");
Finder finder = new Finder();
System.out.println(finder.getIndex(cities, "C"));
System.out.println("Expected: 0");
System.out.println(finder.getIndex(cities, "S"));
System.out.println("Expected: 2");
System.out.println(finder.getIndex(cities, "D"));
System.out.println("Expected: 4");
System.out.println(finder.getIndex(cities, "X"));
System.out.println("Expected: -1");
}
This code has coverage 50/50 input:
4
- Expected: 0
3
- Expected: 2
4
+ Expected: 4
-1
+ Expected: -1
How to solve this issue?
You claim:
My implementations works
It doesn't look like it to me, based on the tests. Your code is much more complicated than it needs to be, which is making it hard to find the bug. The problem is that you've got two loops for no reason:
while (!found && i < text.size()) //supply condition
{
for (String s : text) {
}
}
Why have you got both of those loops? You're incrementing i multiple times within the inner loop...
You'd probably find it easier to get all the tests to pass if you simplify it:
public int getIndex(List<String> text, String target) {
for (int i = 0; i < text.size(); i++) {
if (text.get(i).startsWith(target)) {
return i;
}
}
return -1;
}
This is one of those cases where a dogmatic insistence on only having one return statement per method leads to much messier code.
Note that I've changed the condition from contains (in your code) to startsWith to match the description. You should add a test for this difference - try to find a string which is present in one of the cities, but the city doesn't start with that value.
I've also changed the parameter type to List<String> as you don't really need it to be an ArrayList<String>. (With a bit of work you could make it accept Iterable<String> instead, but that would be more complicated.)
I'd also recommend that you start using JUnit or something similar for your testing, rather than just using System.out.println.
EDIT: Just for a bit of fun, a version which takes Iterable<String> and uses that to handle even LinkedList<String> efficiently:
public int getIndex(Iterable<String> elements, String target) {
int index = 0;
for (String element : elements) {
if (element.startsWith(target)) {
return index;
}
index++;
}
return -1;
}
(Not that much harder after all...)
public int getIndex(ArrayList<String> text, String target)
{
for(int i=0;i < text.size();i++)
{
if(text.get(i).indexOf(target) == 0)
return i;
}
return -1;
}
Making the following changes:
Get rid of unnecessary found variable
Replace contains with startsWith
Remove the for-loop, otherwise you pass through the data a few times
Change the while-loop to a for-loop
I get to this, which seems to work:
public int getIndex(ArrayList<String> text, String target)
{
int index = -1;
for (int i = 0; index == -1 && i < text.size(); i++)
{
if (text.get(i).startsWith(target))
{
index = i;
}
}
return index;
}
You can of course improve on it a lot more still.
Change the getIndex method with this:
public int getIndex(ArrayList<String> text, String target)
{
int i = 0;
for (String s : text) {
// Use startsWith if you want to check if the string starts with target...
// Use contains if you want to check if contains target...
if (s.startsWith(target)) {
return i;
}
i++;
}
return -1;
}
I have an arrayList which contains Objects. Each object contains a number of strings. I am trying to take these strings and add them to a two dimensional array.
public void iterateRow(Row row)
{
int x = 0;
int y = size();
tableArray = new String[y][5];
while(x < y){
int z = 0;
for (String s: row.rowString()){
tableArray[x][z] = s;
z++;
}
x++;
}
}
Whenever i run and create a new instance for the row class the method should add the strings contained in Row to the array. However it duplicates the latest entry x times (where x is the total number of entries).
Here is the Row class for further reference:
public class Row
{
public String appNumber;
public String name;
public String date;
public String fileLoc;
public String country;
public String elementString;
public String results[];
public Row(String appNumber, String name, String date, String fileLoc, String country, Table table)
{
this.appNumber = appNumber;
this.name = name;
this.date = date;
this.fileLoc = fileLoc;
this.country = country;
table.addApplicant(this);
}
public String[] rowString()
{
String[] a = {appNumber, name, date, fileLoc, country};
return a;
}}
I think it is a silly logical error in the iterateRow() method but i can't seem to work out what. Any help would be appreciated.
Edit: After everybody's help i have removed the while loop. However it still seems to be duplicating the Row rather than moving onto the next?
public void iterateRow(Row row)
{ int x = 0;
int y = size();
tableArray = new String[y][row.rowString().length];
for(int i =0; i<y;i++){
int z = 0;
for (String s: row.rowString()){
tableArray[x][z] = s;
z++;
}x++;}
}
The problem looks like it is in the while loop. If size() returns 3, for example, then the while loop will execute with x=0,1,2 so you'll assign tableArray[0], then tableArray[1] and then tableArray[2].
Its hard to tell what the solution is as I can't understand why you've got the while loop in the code at all.
It looks like you want to iterate through each element of a List of Rows
Maybe you want to use a method similar to the following:
public void iterateRows(List<Row> rows) {
int cols = 5;
int row = 0, col = 0;
tableArray = new String[rows.size()][cols];
for(Row row : rows) {
col = 0;
for(String c : row.rowString()) {
tableArray[row][col] = c;
col++;
}
row++:
}
}
However, it would be good to implement your own error checking incase there are more than 5 columns...
EDIT
This is probably not the best design to use for your program, and I would recommend changing it so that when a new row is added, you don't have to iterate through each of the old rows as well.
Your iterateRow method re-creates tableArray each time it is called. Because of the while loop, your Row object gets replicated y times in the array.
I suspect that you want to create your array outside of the iterateRow method and not use a while loop (just the for loop) to populate the next slot in your array.
You are not taking care to size the two dimensional array relative to the size of the Row.
While this might not be the smoking gun, it would be far safer to do
tableArray = new String[y][row.rowString().length];
instead of
tableArray = new String[y][5];
I don't know if this is for practical purpose or how IterateRow() is called, but a logical way to get this working would be to declare the array first, add 2 argument in IterateRow(reference of the array and currentRow). Then, inside iterateRow you get rid of the while loop and you just loop for the string proprieties.
Java newbie, what I am trying to do is retrieve a string name that prints to the screen if one of the multiple values is within a range as follows:
public class SuperHeroes {
private Map<String, Set<Integer>> names;
private Set<Integer> pageNum;
/**
* Constructor for objects of class SuperHeroes
*/
public SuperHeroes() {
names = new HashMap<>();
pageNum = new TreeSet<>();
}
/**
* The fill() method creates 2 entries.
*/
public void fill() {
pageNum.add(1);
pageNum.add(3);
pageNum.add(7);
names.put("Kent,Clark", pageNum);
pageNum = new TreeSet<>();
pageNum.add(2);
pageNum.add(6);
pageNum.add(4);
names.put("Wayne,Bruce", pageNum);
}
public void findInRange(int num, int numb) {
for (String eachName: names.keySet()) {
for (int eachNum:pageNum) {
if(eachNum >= num && eachNum <= numb) {
System.out.println(names.get(eachName));
}
}
}
}
}
The result printed to screen would be the name of superhero if the pageNum is within the range. thr output I get at the moment is all the numbers. Any help would be gratefully received. If you can point me in the right direction would be a help.
Thank you in advance.
First mistake in your code is the way you defined names and pageNum. It should be in this way:
public SuperHeroes()
{
names = new HashMap<String, Set<Integer>>();
pageNum = new TreeSet<Integer>();
}
Now You could use subSet() method of Treeset to achieve what you looking for . Here the code goes:
EDIT: While retrieving the Treeset for given name from names the returned value is needed to be typecast to TreeSet type. Same is to be done while using the subset method with tSet .
public void findInRange(int num, int numb)
{
for (String eachName: names.keySet())
{
TreeSet<Integer> tSet = (TreeSet<Integer>)names.get(eachName);
TreeSet<Integer> subSet = new TreeSet<Integer>();
subSet = (TreeSet<Integer>)tSet.subSet(num,true,numb,true);//for JDK 1.6 or above. returns num<=numbers<=numb
//TreeSet<Integer> subSet = tSet.subSet(num-1, numb+1);//for JDK version less than 1.6
if (subSet.size() != 0)
{
System.out.println("Hero is "+eachName);
break;//you can ommit it if you want to print all heroes having pagenum in range num to numb
}
}
}
The fill method is also needed to be modified as:
public void fill()
{
pageNum.add(1);
pageNum.add(3);
pageNum.add(7);
names.put("Kent,Clark", pageNum);
pageNum = new TreeSet<Integer>();//Use proper way of object construction with generics
pageNum.add(5);
pageNum.add(6);
pageNum.add(4);
names.put("Wayne,Bruce", pageNum);
}
First, you must use the name of the super hero for obtaining the treeset, then read every item in the tree and compare it with the number you need, if the comparison is true print the name of the superhero.
Look at this link
http://www.easywayserver.com/blog/java-treeset-example/
Best regards
You're telling it to print the numbers corresponding to the found name with the line
System.out.println(names.get(eachName));
If you only want to show the name, that should just be
System.out.println(eachname);
Well we are all guessing here. Maybe you need this :
public void findInRange(int num, int numb)
{
for (String eachName : names.keySet())
{
for (int eachNum : pageNum)
{
if (eachNum >= num && eachNum <= numb)
{
for (int temp = 0; temp < eachNum; temp ++)
{
System.out.println(eachName);
}
}
}
}
}
Wondering, you have initialised an pageNum in the constructor, why you are creating another one in the method fill()? That maybe the reason because the one in constructor may "hiding" from the second one in the fill method.
If anybody is interested I solved this with the following code:
public void findInRange(int num, int numb)
{
for(String eachName: names.keySet())
{
pageNum = names.get(eachName);
for (int eachNum:pageNum)
{
if(eachNum>=num&&eachNum<=numb||eachNum>=numb&&eachNum<=num)
{
System.out.println(eachName);
break;
}
}
}
}
For example if you are searching through an array that deals with parts and you are trying to find the first element in that array that has a certain weight. Like if the weight was 10 and in the parts array the first element(part) had a weight of 15 and the second element(part) had a weight of 10 it would return that element. These are the methods that I used.I need to make another method though and I think I might need to call one of these.
class Robot {
Part[] parts;
public Robot () { // implementation is not shown }
public void addPart(PArt p) { // implementation not shown }
}
class Part {
// Class details not shown
public double getWeight() {
}
public int get Partnum() {
}
public getMaterial() {
}
}
First off ... you can't use a double and expect things to compare as you expect. Floating point numbers are not precise. You should use BigDecimal or change to using the lowest commmon denominator (e.g. ounces or grams) represented as an int for your weight.
After that ... iterate through the array until you find a match for the weight you're looking for. It's that simple.
public Part findFirst(int weight)
{
// This will allow us to return null if there's no match
Part p = null;
for (int i = 0; i < parts.length; i++)
{
// after changing getWeight() to return an int
if (parts[i].getWeight() == weight)
{
p = parts[i];
break;
}
}
return p;
}
double searchForLen = 10.00;
for (int i=0; i < parts.length; i++) {
if (parts[i].getWeight() == searchForLen) {
return parts[i];
}
}
I would take Brian's advice and change the type of the weight. If you insist on staying with double you can use Double and then call Double.compare()