1

私が自由になれなかった状況のために、いくつかのサンプルコードであなたの助けが必要です。オブジェクトの簡単なリストがあります。私のクラスは次のようなものです。

class MyClass {
    String str;
    Integer intgr;
}

また、リストには次のような要素が含まれています。

[{a1  5}, {b2  3}, {g1  1}, {b5  1}, {c9  11}, {g2  3}, {d1  4}, {b3  19}... ... ...]

文字列に同じプレフィックスが含まれているかどうかを確認する必要があります(ここでは、サフィックスは最後の1文字です)。次に、整数の値が大きい要素を保持します。上記の例のリストから期待される出力は次のようになります。

[{a1  5}, {c9  11}, {g2  3}, {d1  4}, {b3  19}... ... ...]

文字列には一意の値がありますが、プレフィックスに一致する可能性があります。私はJavaが苦手です。だから誰かがこれから私を助けることができますか?これが私が試しているが取得しているコードですIndexOutOfBoundsException。このコードには誤りがあるので、あなたの助けが必要です。

ありがとう!

        int size = list.size();
        for (int j = 0; j < size; j++) {
        if (list.get(j).str.substring(0, list.get(j).str.length()-1).compareTo(list.get(j+1).str.substring(0, list.get(j+1).str.length()-1)) == 0) {
            if (list.get(j).intgr > list.get(j+1).intgr)
                list.remove(list.get(j+1));
                size--;
            else {
                list.remove(list.get(j));
                j--;
                size--;
            }
        }
    }
4

4 に答える 4

1

要素のコレクションを繰り返し処理してMap、キー(プレフィックス)を値(オブジェクト)に関連付けるように追加することができます。要素が追加されるたびに、同じプレフィックスで保存されている要素が追加されている要素よりも大きいかどうかを確認します。

この動作をするために:

provides this: [{a1 5}, {b2 3}, {g1 1}, {b5 1}, {c9 11}, {g2 3}, {d1 4}, {b3 19}]
results this: [{a1 5}, {c9 11}, {g2 3}, {d1 4}, {b3 19}]

次のようなものを実装できます。

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class TestSystemOut {

    public static void main(final String[] a) {
        List<MyObj> list = prepareList();
        System.out.println("provides this: " + list);

        Map<String, MyObj> map = new LinkedHashMap<String, MyObj>(); // if result order doesn't matter this can be a simple HashMap

        String strTmp;
        for (MyObj obj : list) {

            strTmp = obj.str;
            strTmp = strTmp.substring(0, strTmp.length() - 1);

            if (map.get(strTmp) == null || map.get(strTmp).integer < obj.integer) {
                map.remove(strTmp); // this could be removed if order of result doesn't matter
                map.put(strTmp, obj);
            }
        }

        list.clear();
        list.addAll(map.values());

        System.out.println("results this: " + list);
    }

    public static class MyObj {
        String str;
        Integer integer;

        public MyObj(final String str, final Integer integer) {
            super();
            this.str = str;
            this.integer = integer;
        }

        @Override
        public String toString() {
            return "{" + str + " " + integer + "}";
        }

    }

    private static List<MyObj> prepareList() {
        List<MyObj> list = new ArrayList<MyObj>();
        list.add(new MyObj("a1", 5));
        list.add(new MyObj("b2", 3));
        list.add(new MyObj("g1", 1));
        list.add(new MyObj("b5", 1));
        list.add(new MyObj("c9", 11));
        list.add(new MyObj("g2", 3));
        list.add(new MyObj("d1", 4));
        list.add(new MyObj("b3", 19));
        return list;
    }
}
于 2012-06-27T18:44:30.107 に答える
0

別の(おそらく読みやすくデバッグしやすい)方法は次のとおりです。

  1. アイテムをリストに入れる
  2. リストを繰り返し処理し、Stringが文字で、MyClassが最小であるマップにデータを入力します(つまり、マップに「a」の何かがすでに含まれている場合は、新しいMyClassが大きいか小さいかを確認し、それに応じて置き換えます)

簡単な実装:

public class Test {

    public static void main(String[] args) throws InterruptedException {
        List<MyClass> list = Arrays.asList(new MyClass("a1", 5),
                new MyClass("b2",  3),
                new MyClass("g1",  1),
                new MyClass("b5",  1),
                new MyClass("c9",  11),
                new MyClass("g2",  3),
                new MyClass("d1",  4),
                new MyClass("b3",  19));

        Map<String, MyClass> map = new HashMap<String, MyClass>();

        for (MyClass mc : list) {
            MyClass current = map.get(mc.getLetter());
            if (current == null || mc.intgr > current.intgr) {
                map.put(mc.getLetter(), mc);
            }
        }
        System.out.println(map);
    }

    static class MyClass  {

        String str;
        Integer intgr;

        MyClass(String str, Integer intgr) {
            this.str = str;
            this.intgr = intgr;
        }
        String getLetter() {
            return str.substring(0,1);
        }

        @Override
        public String toString() {
            return "[" + str + " " + intgr + "]";
        }
    }
}
于 2012-06-27T18:45:29.540 に答える
0
/*
 * For every string in the list, look at all strings in the
 * list and compare the substring from 0 to length-1, if they
 * match and the id is not the same as the current s (i.e. s and
 * list.get(i) are at the same address) then remove that string.
 */
public ArrayList remdup(ArrayList<String> list) {

    for (String s : list) {
        for (int i=0; i<list.size();i++) {
            if (s.substring(0, s.length()-1).compareTo(list.get(i).substring(0, list.get(i).length()-1)) == 0
                    && list.indexOf(list.get(i)) != list.indexOf(s)) {
                list.remove(list.get(i));
            }
        }
    }
    return list;
}

たぶんこれを試してみてください。まだテストしていませんが、うまくいくはずです。compareTo()とは異なるものを使用しようとしない場合は、代わりにequals()を使用してください。

また、要素を削除するたびにサイズが差し引かれ、検索領域が小さくなるため、IndexOutOfBoundsExceptionが発生します。remove()がこれを行うことを考慮していません。

これには、クラスの代わりにマップを使用することを検討します。そうすれば、車輪の再発明に取り掛かる必要はありません。

于 2012-06-27T19:01:49.637 に答える
0

コードには2つの問題があります。まず、j == size - 1(最後の反復)のときに、list.get(j + 1)を呼び出しています。これが、例外の原因です。ループ条件をに変更するだけj < size - 1で、例外はなくなります。(または、j = 1前の要素から始めて比較します。)

次に、各要素をその直後の後続要素とのみ比較しています。あなたの説明から、それはあなたがやりたいことのようには聞こえません。

別の方法で比較のロジックをキャプチャすることをお勧めします。の一部である可能性がありますMyClass

class MyClass {
    String str;
    Integer intgr;
    /**
     * Returns the relationship between this and another MyClass instance.
     * The relationship can be one of three values:
     * <pre>
     *   -1 - This object should be discarded and other kept
     *    0 - There is no relationship between this and other
     *    1 - This object should be kept and other discarded
     * </pre>
     *
     * @param other The other instance to evaluate
     *
     * @return 0 if there is no relationship.
     */
    public int relationTo(MyClass other) {
        final String myPrefix = str.substring(0, str.length() - 1);
        final String otherPrefix = other.str.substring(0, other.str.length() - 1);
        if (myPrefix.equals(otherPrefix)) {
            return intgr < other.intgr ? -1 : 1;
        } else {
            return 0;
        }
    }
}

(これは、外部にある2つの引数を持つメソッドに簡単に変換できますMyClass。)次に、メソッドを使用して、何を保持するかを決定できます。隣接していないオブジェクトを見つけるには、2回の反復を行う必要があります。

int size = list.size();
for (int i = 0; i < size; ++i) {
    final MyClass current = list.get(i);
    for (int j = 0; j < i; ++j) {
        final MyClass previous = list.get(j);
        final int relation = previous.relationTo(current);
        if (relation < 0) {
            // remove previous (at index j)
            list.remove(j);
            --i;
            --j;
            --size;
        } else if (relation > 0) {
            // remove current (at index i)
            list.remove(i);
            --i;
            --size;
            break; // exit inner loop
        }
        // else current and previous don't share a prefix
    }
}
于 2012-06-27T19:27:06.263 に答える