How can I parse a string for a set?

2019-08-11 08:13发布

I am writing a method that is supposed to take an input String of the format "s1:{1,2,3,4}" and put it into a Set. The set class I have developed myself, and is as follows:

public class Set<E> implements Iterable<E> {
    private static final int DEFAULT_CAPACITY = 20;
    private String name;
    private E[] theData;
    private int size = 0;
    private int capacity = 0;

    public Set(){
        capacity = DEFAULT_CAPACITY;
        theData = (E[]) new Object[capacity];
    }//end constructor

    public Set(String name){
        capacity = DEFAULT_CAPACITY;
        theData = (E[]) new Object[capacity];
        this.name = name;
    }//end constructor

    public String getName(){
        return name;
    }//end getName

    public void setName(String name){
        this.name = name;
    }//end setName

    //adds object to set
    public void add(Object E) {
        if (size == capacity) {
            reallocate();
        }//end if

        theData[size] = (E) E;
        size++;

        for (int j = 0; j<size; j++) {
            for (int k = 0; k < size; k++) {
                if ((int)theData[j] < (int)theData[k]) {
                    E temp = theData[j];
                    theData[j] = theData[k];
                    theData[k] = temp; 
                }//end if
            }//end nested for loop
        }//end for loop

        int counter = 0;
        for (int i = 0; i < size; i++) {
            if (E == theData[i]) {
                counter++;

                if (counter >= 2) {
                    remove((Object)E);
                 }//end nested if
            }//end if
        }//end for loop
    }//end add method

    public E get(int i) {
        if (i < 0 || i >= size) {
            throw new ArrayIndexOutOfBoundsException(i);
        } else {
            return theData[i];
        }//end else 
    }//end get method

    public E remove(int i) {
        if (i < 0 || i >= size) {
            throw new ArrayIndexOutOfBoundsException(i);
        }//end if

        E returnValue = theData[i];
        for (int j = i + 1; j < size; j++) {
            theData[j - 1] = theData[j];
        }//end for loop

        size--;
        return returnValue;
    }//end remove method

    public void remove(Object E) {
        for (int i = 0; i < size; i++) {
            if (E == theData[i]) {
                for (int j = i + 1; j < size; j++){
                    theData[j - 1] = theData[j];
                }//end nested for loop

                size--;
            }//end if
        }//end for loop
    }//end remove method

    //fix!
    public int find(Object E) {
        int first, last, middle;
        first = 0;
        last = size - 1;
        middle = (first+last) / 2;

        while(first <= last ) {
            if ((int)theData[middle] > (int)E ) {
                last = middle - 1;    
            } else if ((int)theData[middle] < (int)E ) {
                first = middle + 1;
            } else {
                return middle;
            }//end else
        }//end while

        if (first > last) {
            return -1;
        }//end if

        return -1;
    }//end find method

    public Set<E> union(Set<E> s) {
        Set<E> returnSet = new Set<E>();

        for (int i = 0; i < this.size; i++) {
            returnSet.add(this.theData[i]);
        }//end for loop

        for (int i = 0; i < s.size; i++) {
            returnSet.add(s.theData[i]);
        }//end for loop

        return returnSet;
    }//end union method

    public Set<E> intersect(Set<E> s) {
        Set<E> returnSet = new Set<E>();

        for (int i = 0; i < this.size; i++) {
            for (int j = 0; j < s.size; j++) {
                if (this.theData[i] == s.theData[j]){
                    returnSet.add(theData[i]);
                }//end if
            }//end nested for loop
        }//end for loop

        return returnSet;
    }//end intersect method

    public Set<E> subtract(Set<E> s) {
        Set<E> returnSet = new Set<E>();

        for (int i = 0; i < this.size; i++) {
            for (int j = 0; j < s.size; j++) {
                if (this.theData[i] == s.theData[j]) {
                    this.remove((Object)this.theData[i]);
                    s.remove((Object)s.theData[j]);
                }//end if
            }//end nested for loop
        }//end for loop

        for (int i = 0; i < this.size; i++) {
            returnSet.add(this.theData[i]);
        }//end for loop

        for (int i = 0; i < s.size; i++) {
            returnSet.add(s.theData[i]);
        }//end for loop

        return returnSet;
    }//end subtract method

    public boolean equals(Set<E> s) {
        boolean result = false;

        for (int i = 0; i < this.size; i++) {
            if (this.theData[i] == s.theData[i]) {
                result = true;
            }//end if

            if (this.theData[i] != s.theData[i]) {
                result = false;
                break;
            }//end if
        }//end for loop

        return result;
    }//end equals method


    private void reallocate() {
        capacity = 2*capacity;
        theData = Arrays.copyOf(theData,  capacity);
    }//end reallocate method

    public String toString() {
        StringBuilder set = new StringBuilder();
        set.append("{");

        for (int i = 0; i < size; i++) {
            set.append(theData[i]);

            if (i != size-1){
                set.append(",");
            }//end if
        }//end for loop

        set.append("}");

        return set.toString();
    }//end toString()

    public SetIterator<E> iterator() {
        SetIterator<E> it = new SetIterator<E>() {
            private int currentIndex = 0;

            public boolean hasNext() {
                if (currentIndex < size && theData[currentIndex] != null){
                    currentIndex++;
                    return true;
                } else{
                    return false;
                }//end else
            }//end hasNext()


            public E next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();
                }//end if

                return theData[currentIndex++];
            }//end next()


            public boolean hasPrevious() {
                if (currentIndex <= size && currentIndex > 0) {
                    currentIndex--;
                    return true;
                } else {
                    return false;
                }//end else
            }//end hasPrevious()


            public E previous() {
                if (!hasPrevious()) {
                    throw new NoSuchElementException();
                }//end if

                return theData[currentIndex--];
            }//end previous()


            public void add(E item) {
                theData[currentIndex-1] = item;
            }//end add()


            public void remove() {
                for (int i = 0; i < size; i++) {
                    if (theData[currentIndex] == theData[i]) {
                        for (int j = i + 1; j < size; j++) {
                            theData[j - 1] = theData[j];
                        }//end nested for loop

                        size--;
                    }//end if
                }//end for loop
            }//end remove()
        };//end new SetIterator()

        return it;
    }//end iterator method
}//end Set class

The method is should

  • throw an exception if the method has invalid format such as "s1:[1 2,3,4}" (This example being the missing comma and curly brace).
  • additionally, the input may have any number of whitespaces and will still be considered valid. Example: "s1: {1, 2, 3, 4 }".

So far all I have for the method is:

public Set<Integer> parse(String input){
    String s[] = input.split(":");
    String name = s[0];
    Set<Integer> returnSet = new Set<Integer>(name);

    return returnSet;
}

I am unsure as to how to properly retrieve the elements out of the set in the string and put them into a Set object. I know I can parseInt once I get them by themselves but I am having trouble isolating each element. There is no limit on how many elements a set can have; which means my code should work with any number of elements.

I have also considered regular expressions but I feel as if there's a more efficient way of doing this.

Any help will be appreciated!

3条回答
贪生不怕死
2楼-- · 2019-08-11 08:29

The easiest Way is to use the constructor of the Set

http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html

along with Arrays.asList()

http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html

to convert your String[] into a Set<String>:

Set<String> mySet = new HashSet<String>(Arrays.asList(s));
查看更多
等我变得足够好
3楼-- · 2019-08-11 08:48

This is a working example: First you will create a regexp pattern to match the inner of {} then you will check the inner of {} weather it is correctly formated. Then you will convert the inner of {} to an ArrayList.

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.*;

public class Test {

    public String test = "s 1 : {1, 2,3 ,4}";

    public Test() {
        //match the inside of {}
        Pattern pattern = Pattern.compile("^s\\s*\\d+\\s*:\\s*\\{([0-9,\\s*]*)}");

        Matcher matcher = pattern.matcher(test);


        // check all occurance
        while (matcher.find()) {
            if(matcher.group(1).trim().matches("^(\\d*)+(\\s*,\\s*\\d*)*$")) {
                System.out.println("valid string");
                List<String> items = Arrays.asList(matcher.group(1).split("\\s*,\\s*"));
                for(String number: items) {
                    System.out.println(number.trim());
                }
            }else{
                System.out.println("invalid string");
            }
        }
    }

    public static void main(String[] args) {
        new Test();
    }
}
查看更多
你好瞎i
4楼-- · 2019-08-11 08:49

I've given you the minimal code needed. This will match or return null. Then you get the label and String set. If you really do need the Integer object, you can convert as simple as f2() below. What you need to add is error handling and more comments. Look at the JavaDoc API for more info on Pattern/Matcher. Also, don't simply use a HashSet. If order matters to you, you need at least a LinkedHashSet. If duplicates are allowed, DO NOT use Hash anything! Use a LinkedList or array.

Btw, your method of splitting the string is not wrong, but it will be more complex. You have to split by :, then call str.trim() to remove any extra spaces, str.substring( startIndx, endIndex), and then finally you can parse the number list. You will have to either use str.indexOf("{") or search manually to get the indices.

import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class NewClass {

    //match this
    //STR:{NUM_LIST}
    //[A-Za-z0-9_]+ = STR is upper and lower alpha, number or underscore; 1 or more characters (in any order)
    //[0-9,]+ = NUM_LIST is one or more characters and can only contain numbers or comma (in any order)
    //The () used will give us a group
    //I like to explicitly use [] to specify a character, but it may not be needed
    //use a slash (needs a 2nd because of Java) to make sure it is interpreted as just a character and not as a structure of syntax.
    Pattern p=Pattern.compile("([A-Za-z0-9_]+)[:][\\{]([0-9,]+)[\\}]");

    Set test(String txt){
        Matcher m=p.matcher(txt);
        if(!m.matches())return null;
        int groups=m.groupCount();//should only equal 3 (default whole match+2groups) here, but you can test this

        System.out.println("Matched: " + m.group(0));
        String label = m.group(1);
        String[] arr = m.group(2).split(",");

        Set<String> set = new LinkedHashSet(Arrays.asList(arr));

        return set;
    }

     Object[] test2(String txt){
        Matcher m=p.matcher(txt);
        if(!m.matches())return null;
        int groups=m.groupCount();//should only equal 3 (default whole match+2groups) here, but you can test this

        System.out.println("Matched: " + m.group(0));
        String label = m.group(1);
        String[] arr = m.group(2).split(",");

        Set<String> set = new LinkedHashSet(Arrays.asList(arr));
        Object[] ret=new Object[3];
        ret[0] = m.group(0);
        ret[1] = label;
        ret[2] = set;
        return ret;
    }
}


 void f2(String[] arr){
     ArrayList<Integer> list=new ArrayList<Integer>(1000);
     for(String s: arr){
         try {
             list.add(Integer.parseInt(s));
         } catch (NumberFormatException numberFormatException) {
             System.out.println(numberFormatException+ "\t-->\t"+ s);
         }
     }
    Set<Integer> set = new LinkedHashSet(list);
 }
查看更多
登录 后发表回答