Bir n Nesne dizisi verildiğinde , diyelim ki bu bir dizi dizisidir ve aşağıdaki değerlere sahiptir:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
Dizideki "a" 'ya eşit tüm dizeleri / nesneleri silmek / kaldırmak için ne yapmalıyım ?
Bir n Nesne dizisi verildiğinde , diyelim ki bu bir dizi dizisidir ve aşağıdaki değerlere sahiptir:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
Dizideki "a" 'ya eşit tüm dizeleri / nesneleri silmek / kaldırmak için ne yapmalıyım ?
Yanıtlar:
[Kullanıma hazır bir kod istiyorsanız, lütfen "Düzenleme3" e gidin (kesimden sonra). Gerisi gelecek nesil için burada.]
Dustman'ın fikrini ortaya çıkarmak için :
List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);
Düzenleme: Şimdi kullanıyorum Arrays.asList
yerine Collections.singleton
: oysa tekil, bir giriş ile sınırlıdır asList
yaklaşım daha sonra süzmek için diğer dizeleri eklemenizi sağlar: Arrays.asList("a", "b", "c")
.
Düzenleme2: Yukarıdaki yaklaşım aynı diziyi korur (bu nedenle dizi hala aynı uzunluktadır); sondan sonraki öğe null olarak ayarlanır. Tam olarak gerektiği gibi boyutlandırılmış yeni bir dizi istiyorsanız , bunun yerine şunu kullanın:
array = list.toArray(new String[0]);
Düzenleme3: Bu kodu aynı sınıfta sık sık kullanıyorsanız, bunu sınıfınıza eklemeyi düşünebilirsiniz:
private static final String[] EMPTY_STRING_ARRAY = new String[0];
Ardından işlev şu hale gelir:
List<String> list = new ArrayList<>();
Collections.addAll(list, array);
list.removeAll(Arrays.asList("a"));
array = list.toArray(EMPTY_STRING_ARRAY);
Bu daha sonra öbeğinizi new
, işleviniz her çağrıldığında başka türlü kullanılabilecek gereksiz boş dize dizileriyle doldurmayı bırakacaktır .
alaycı'nın önerisi (yorumlara bakın) aynı zamanda çöp yığınına da yardımcı olacaktır ve adalet için bundan bahsetmeliyim:
array = list.toArray(new String[list.size()]);
Yaklaşımımı tercih ederim çünkü açık boyutu yanlış anlamak daha kolay olabilir (örneğin, size()
yanlış listeyi aramak).
Java 8'de bir alternatif:
String[] filteredArray = Arrays.stream(array)
.filter(e -> !e.equals(foo)).toArray(String[]::new);
Stream.of(foo).filter(s -> ! s.equals("a")).toArray()
yeterli olur.
İle List
diziden bir çıkış yapın Arrays.asList()
ve remove()
tüm uygun öğeleri çağırın . Ardından toArray()
tekrar bir diziye dönmek için 'Liste'yi çağırın .
Çok fazla performans göstermez, ancak onu doğru bir şekilde özetlerseniz, daha sonra her zaman daha hızlı bir şeyler yapabilirsiniz.
Arrays.asList()
desteklemediğine dikkat çekti remove()
. Peki bu cevap tamamen geçersiz mi? Görünüşe göre bazı yorumlar kaldırılmış olabilir, bu yüzden bunun tartışılıp tartışılmadığını bilmiyorum.
Her zaman yapabilirsiniz:
int i, j;
for (i = j = 0; j < foo.length; ++j)
if (!"a".equals(foo[j])) foo[i++] = foo[j];
foo = Arrays.copyOf(foo, i);
Harici kitaplığı kullanabilirsiniz:
org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)
Apache Commons Lang projesinde http://commons.apache.org/lang/
ArrayUtils.removeElement(boolean[] array, boolean element)
ayrıca çok kullanışlıdır.
List
Ek diziye dönüştürmeden veya ek dizi oluşturmadan diziden birden çok öğeyi kaldırmanız gerekirse, bunu, kaldırılacak öğelerin sayısına bağlı olmaksızın O (n) içinde yapabilirsiniz.
Burada, a
ilk dizi, int... r
kaldırılacak öğelerin ayrı sıralı indisleridir (konumları):
public int removeItems(Object[] a, int... r) {
int shift = 0;
for (int i = 0; i < a.length; i++) {
if (shift < r.length && i == r[shift]) // i-th item needs to be removed
shift++; // increment `shift`
else
a[i - shift] = a[i]; // move i-th item `shift` positions left
}
for (int i = a.length - shift; i < a.length; i++)
a[i] = null; // replace remaining items by nulls
return a.length - shift; // return new "length"
}
Küçük testler:
String[] a = {"0", "1", "2", "3", "4"};
removeItems(a, 0, 3, 4); // remove 0-th, 3-rd and 4-th items
System.out.println(Arrays.asList(a)); // [1, 2, null, null, null]
Görevinizde, önce "a" nın pozisyonlarını toplamak için diziyi tarayabilir, sonra çağırabilirsiniz removeItems()
.
Burada pek çok yanıt var - gördüğüm kadarıyla sorun, NEDEN bir koleksiyon yerine bir dizi kullandığınızı söylememiş olmanızdır, bu nedenle birkaç neden ve hangi çözümlerin geçerli olacağını önereyim (Çözümlerin çoğu buradaki diğer sorularda zaten yanıtlandı, bu yüzden çok fazla ayrıntıya girmeyeceğim):
sebep: Koleksiyon paketinin var olduğunu bilmiyordunuz veya ona güvenmediniz
çözüm: Bir koleksiyon kullanın.
Ortadan eklemeyi / silmeyi planlıyorsanız, bir LinkedList kullanın. Boyut konusunda gerçekten endişeleniyorsanız veya genellikle koleksiyonun tam ortasına dizin oluşturuyorsanız, bir ArrayList kullanın. Bunların her ikisinin de silme işlemleri olmalıdır.
neden: Boyut konusunda endişelisiniz veya bellek tahsisi üzerinde kontrol istiyorsanız
çözüm: Belirli bir başlangıç boyutuna sahip bir ArrayList kullanın.
Bir ArrayList, basitçe kendini genişletebilen bir dizidir, ancak her zaman bunu yapması gerekmez. Öğeleri ekleme / çıkarma konusunda çok akıllıca olacaktır, ancak ortada bir LOT ekliyor / çıkarıyorsanız, bir LinkedList kullanın.
sebep: Gelen bir dizi var ve çıkan bir dizi var - bu yüzden bir dizi üzerinde işlem yapmak istiyorsunuz
çözüm: ArrayList'e dönüştürün, öğeyi silin ve geri dönüştürün
neden: Kendiniz yaparsanız daha iyi kod yazabileceğinizi düşünüyorsunuz
çözüm: Bir Dizi veya Bağlantılı liste kullanamazsınız.
neden: bu bir sınıf ödevidir ve izniniz yok veya bazı nedenlerden dolayı koleksiyon apislerine erişiminiz yok
varsayım: Yeni dizinin doğru "boyutta" olması gerekir
çözüm: Diziyi eşleşen öğeler için tarayın ve sayın. Doğru boyutta yeni bir dizi oluşturun (orijinal boyut - eşleşme sayısı). Saklamak istediğiniz her öğe grubunu yeni Dizinize kopyalamak için System.arraycopy'yi tekrar tekrar kullanın. Bu bir sınıf ödeviyse ve System.arraycopy kullanamıyorsanız, bunları teker teker elle bir döngüde kopyalayın, ancak bunu üretim kodunda yapmayın çünkü çok daha yavaştır. (Bu çözümlerin her ikisi de diğer yanıtlarda detaylandırılmıştır)
sebep: çıplak metal çalıştırmanız gerekiyor
varsayım: Gereksiz yere yer ayırmamalısınız veya çok uzun sürmemelisiniz
varsayım: Dizide (uzunluk) kullanılan boyutu ayrı ayrı izliyorsunuz çünkü aksi takdirde dizinizi silme / eklemeler için yeniden tahsis etmeniz gerekir.
Bunu neden yapmak isteyebileceğinize bir örnek: tek bir ilkel dizi (Diyelim ki int değerleri) ramınızın önemli bir bölümünü alıyor -% 50 gibi! Bir ArrayList, bunları birkaç kat bellek kullanan Tamsayı nesnelerine işaret eden bir listeye zorlar.
çözüm: Dizinizi yineleyin ve kaldırılacak bir öğe bulduğunuzda (buna öğe n diyelim), dizinin kuyruğunu "silinmiş" öğenin üzerine kopyalamak için System.arraycopy kullanın (Kaynak ve Hedef aynı dizidir) - kopyalamayı doğru yönde yapacak kadar akıllıdır, böylece bellek kendi üzerine yazmaz:
System.arraycopy (ary, n + 1, ary, n, length-n) uzunluk--;
Bir seferde birden fazla öğeyi siliyorsanız, muhtemelen bundan daha akıllı olmak isteyeceksiniz. Alanı tüm kuyruk yerine yalnızca bir "eşleşme" ve sonraki arasında hareket ettirirsiniz ve her zaman olduğu gibi, herhangi bir parçayı iki kez hareket ettirmekten kaçınırsınız.
Bu son durumda, işi kesinlikle kendiniz yapmalısınız ve System.arraycopy kullanmak gerçekten bunu yapmanın tek yoludur, çünkü bilgisayar mimariniz için belleği taşımak için olası en iyi yolu seçecektir - birçok kez daha hızlı olmalıdır kendi kendinize yazabileceğiniz herhangi bir koddan daha fazla.
Bunun bir listesini yapmak ve sonra bir diziye geri dönmekle ilgili bir şey bana yanlış geliyor. Test etmedim, ancak aşağıdakilerin daha iyi performans göstereceğini düşünüyorum. Evet, muhtemelen gereksiz yere önceden optimize ediyorum.
boolean [] deleteItem = new boolean[arr.length];
int size=0;
for(int i=0;i<arr.length;i==){
if(arr[i].equals("a")){
deleteItem[i]=true;
}
else{
deleteItem[i]=false;
size++;
}
}
String[] newArr=new String[size];
int index=0;
for(int i=0;i<arr.length;i++){
if(!deleteItem[i]){
newArr[index++]=arr[i];
}
}
Bunun çok eski bir yazı olduğunun farkındayım, ama buradaki bazı cevaplar bana yardımcı oldu, işte benim tuppence 'ha'penny'nin değeri!
Tekrar yazdığım dizinin yeniden boyutlandırılması gerektiğine karar vermeden önce, bunu çalıştırmak için epeyce uğraştım. ArrayList
Liste boyutunda yapılan değişiklikler değişmeden bırakılmadıkça, .
Eğer ArrayList
konum modifiye o ile başlayan daha büyük ya da daha az sayıda unsurları ile biter sen misin, çizgi List.toArray()
istisna neden olur, gibi bir şey lazım bu yüzden List.toArray(new String[] {})
yaList.toArray(new String[0])
yeni (doğru) boyutu ile bir dizi yaratmak amacıyla.
Şimdi bildiğime göre açık görünüyor. Yeni ve alışılmadık kod yapılarıyla uğraşan ve buradaki önceki yayınların bazılarından anlaşılmayan bir Android / Java acemi için o kadar açık değil, bu yüzden bu noktayı, benim gibi saatlerce kafasını kaşıyan herhangi biri için gerçekten açık hale getirmek istedim !
DÜZENLE:
Dizide boş değerlere sahip nokta temizlendi. Yorumlarım için özür dilerim.
Orijinal:
Ehm ... çizgi
array = list.toArray(array);
kaldırılan öğenin boş olduğu dizideki tüm boşlukları değiştirir . Bu tehlikeli olabilir , çünkü öğeler kaldırılır, ancak dizinin uzunluğu aynı kalır!
Bundan kaçınmak istiyorsanız, toArray () için parametre olarak yeni bir Dizi kullanın. RemoveAll'ı kullanmak istemiyorsanız, bir Set alternatif olabilir:
String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" };
System.out.println(Arrays.toString(array));
Set<String> asSet = new HashSet<String>(Arrays.asList(array));
asSet.remove("a");
array = asSet.toArray(new String[] {});
System.out.println(Arrays.toString(array));
Verir:
[a, bc, dc, a, ef]
[dc, ef, bc]
Chris Yester Young'dan şu anda kabul edilen yanıt şu çıktı:
[a, bc, dc, a, ef]
[bc, dc, ef, null, ef]
kod ile
String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" };
System.out.println(Arrays.toString(array));
List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);
System.out.println(Arrays.toString(array));
Geride boş değer kalmaz.
Bu soruna küçük katkım.
public class DeleteElementFromArray {
public static String foo[] = {"a","cc","a","dd"};
public static String search = "a";
public static void main(String[] args) {
long stop = 0;
long time = 0;
long start = 0;
System.out.println("Searched value in Array is: "+search);
System.out.println("foo length before is: "+foo.length);
for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);}
System.out.println("==============================================================");
start = System.nanoTime();
foo = removeElementfromArray(search, foo);
stop = System.nanoTime();
time = stop - start;
System.out.println("Equal search took in nano seconds = "+time);
System.out.println("==========================================================");
for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);}
}
public static String[] removeElementfromArray( String toSearchfor, String arr[] ){
int i = 0;
int t = 0;
String tmp1[] = new String[arr.length];
for(;i<arr.length;i++){
if(arr[i] == toSearchfor){
i++;
}
tmp1[t] = arr[i];
t++;
}
String tmp2[] = new String[arr.length-t];
System.arraycopy(tmp1, 0, tmp2, 0, tmp2.length);
arr = tmp2; tmp1 = null; tmp2 = null;
return arr;
}
}
"Kaldır" ile ne demek istediğine bağlı mı? Dizi sabit boyutlu bir yapıdır - içindeki elemanların sayısını değiştiremezsiniz. Böylece, a) istemediğiniz öğeler olmadan yeni, daha kısa bir dizi oluşturabilirsiniz veya b) istemediğiniz girişleri 'boş' durumlarını gösteren bir şeye atayabilirsiniz; ilkellerle çalışmıyorsanız genellikle null.
İlk durumda diziden bir Liste oluşturun, elemanları kaldırın ve listeden yeni bir dizi oluşturun. Performans önemliyse, bir listeye kaldırılmaması gereken öğeleri atayarak dizi üzerinde yineleyin ve ardından listeden yeni bir dizi oluşturun. İkinci durumda, dizi girişlerine basitçe gidin ve null atayın.
Arrgh, kodu doğru şekilde gösteremiyorum. Üzgünüm, çalıştırdım. Tekrar özür dilerim, soruyu doğru okuduğumu sanmıyorum.
String foo[] = {"a","cc","a","dd"},
remove = "a";
boolean gaps[] = new boolean[foo.length];
int newlength = 0;
for (int c = 0; c<foo.length; c++)
{
if (foo[c].equals(remove))
{
gaps[c] = true;
newlength++;
}
else
gaps[c] = false;
System.out.println(foo[c]);
}
String newString[] = new String[newlength];
System.out.println("");
for (int c1=0, c2=0; c1<foo.length; c1++)
{
if (!gaps[c1])
{
newString[c2] = foo[c1];
System.out.println(newString[c2]);
c2++;
}
}
Dizeler dizisinde olduğu gibi
Dize adı = 'abcdeafbde' // Dize adı = 'aa bb cde aa f bb de' gibi olabilir
Ben aşağıdaki sınıfı oluşturuyorum
class clearname{
def parts
def tv
public def str = ''
String name
clearname(String name){
this.name = name
this.parts = this.name.split(" ")
this.tv = this.parts.size()
}
public String cleared(){
int i
int k
int j=0
for(i=0;i<tv;i++){
for(k=0;k<tv;k++){
if(this.parts[k] == this.parts[i] && k!=i){
this.parts[k] = '';
j++
}
}
}
def str = ''
for(i=0;i<tv;i++){
if(this.parts[i]!='')
this.str += this.parts[i].trim()+' '
}
return this.str
}}
return new clearname(name).cleared()
bu sonucu almak
abcdef
umarım bu kod herkese yardımcı olur Saygılarımızla
Elementlerin sırası önemli değilse. foo [x] ve foo [0] öğeleri arasında değiş tokuş yapabilir, ardından foo.drop (1) 'i çağırabilirsiniz.
foo.drop(n)
dizideki ilk öğeleri (n) kaldırır.
Sanırım bu, yapmanın en basit ve kaynak açısından verimli yolu.
Not : indexOf
birçok şekilde uygulanabilir, bu benim versiyonum.
Integer indexOf(String[] arr, String value){
for(Integer i = 0 ; i < arr.length; i++ )
if(arr[i] == value)
return i; // return the index of the element
return -1 // otherwise -1
}
while (true) {
Integer i;
i = indexOf(foo,"a")
if (i == -1) break;
foo[i] = foo[0]; // preserve foo[0]
foo.drop(1);
}