去除掉数组中的值为0的项 (指定的某一项或者多项)

本文介绍了一种在Java中将数组转换为List的方法,并通过List集合移除特定元素,最终获得所需的新数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我说下我的思路,由于api中没有直接移除数组中指定项,所以我先吧原数组转换成 list ,在通过list集合来得到自己需要的数组。下面是代码,如有更好的方法,恳请各位拍砖。

import java.util.List;
import java.util.ArrayList;;

public class ArrayTest4 {
	public static void main(String args[]){
		int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5};
		ArrayTest4 at = new ArrayTest4();
		List<Integer> list = at.changeArrayTOList(oldArr);
		at.getTheGoalArray(list);
	}
	/**
	 * 将远数组转化成list
	 * @param list 目标List
	 */
	public  List<Integer> changeArrayTOList(int [] oldArr){
		List<Integer> list = new ArrayList<Integer>();
		for (int i = 0; i < oldArr.length; i++) {
			if(oldArr[i] != 0){
				list.add(oldArr[i]);
			}
		}
		return list;
	}
	/**
	 * 得到最后的需要的数组
	 */
	public void  getTheGoalArray(List<Integer> list){
		int newArr[] = new int[list.size()];
		for (int i = 0; i < list.size(); i++) {
			newArr[i] = list.get(i);
		}
		for (int i = 0; i < newArr.length; i++) {
			System.out.print(newArr[i]+" ");
		}
	}
}


<think>我们有一个数组数组是对象。要求:当遇到某个对象的type为1时,我们需要删除数组中所有与这个对象name相同的其他(包括其他type不为1的同名)。注意:可能存在多个type为1的,并且它们的name可能不同,我们需要对每一个type为1的都执行这样的操作:即删除整个数组中与该name相同的所有(除了该type为1的本身之外的其他同名)。思路:1.首先遍历数组,找出所有type为1的,并记录这些的name(注意:可能有多个type为1的,并且相同的name只需记录一次,因为遇到多个相同name的type1,效果是一样的)。2.然后,我们需要删除数组中所有name在记录集合中,且type不为1的?不对,题目要求是:当某一项的type为1时,删除所有与该name相同的其他(无论这些其他的type是什么,但保留当前这个type为1的)。也就是说,对于每个标记为type1的name,我们只保留数组中第一个(或任意一个)type为1的该?不对,实际上,题目要求是删除所有其他(即所有与type1同名的,除了type1本身之外)。但是注意:数组中可能有多个type为1的,而且它们的name可能不同。因此,我们首先收集所有需要删除的name集合(即所有type为1的的name),然后遍历数组,对于每个元素,如果它的name在这个集合中,且它本身的type不为1,则删除?不对,因为题目要求是:当某一项type为1时,删除所有其他同名(包括type不为1的同名,也包括type为1的同名?)注意:题目要求是“删除所有与该name相同的其他”,这个“其他”就是除了当前这个type为1的之外的所有同名。所以,具体步骤:步骤1:收集所有需要保留的type为1的(因为它们不能被删除),但是注意,如果有多个type为1的且name相同,那么其中每个type为1的都是需要保留的?但是题目说“删除所有其他”,也就是只保留这些type为1的(每个同名组中,所有type为1的都保留?还是只保留一个?)。这里题目没有明确,但根据描述“当某一项的type为1时,删除所有与该name相同的其他”,对于每个type为1的,我们只保留它自己,而删除所有其他同名(包括其他type为1的同名)。所以,如果我们有多个type为1的同名,那么按照要求,每个type为1的都要执行删除其他同名(包括其他type为1的同名),这样就会导致最后只剩下一个type为1的(因为执行第一个时会把后面的同名删除,包括后面的type为1的同名)。这显然不是我们想要的,因为这样后面执行时就会发现前面已经删除了。重新理解题目:数组中可能有多项type为1,且它们可能具有不同的name。对于每一个type为1的,我们都要删除整个数组中除了它自身以外所有name与它相同的(注意:是对于每一个type1的,都执行一次删除操作,但是删除操作会删除其他同名,包括其他type1的同名)。问题:如果两个type1的具有相同的name,那么执行第一个type1的操作时,会删除第二个type1(因为同名且是其他),然后执行到第二个type1时,它已经被删除了,或者我们如何避免?因此,我们需要重新规划:我们实际上是要删除所有在某个“需要删除的name”集合中,且不是我们标记为保留的(即不是我们遇到的那个type1的)的。但是,我们可能希望每个同名组中只保留一个type1的?题目没有明确保留哪一个,所以我们可以保留所有遇到的type1的(只要在删除时不删除自身)。所以,我们分两步:1.构建一个要删除的列表(或标记数组),先不实际删除,以免遍历过程中数组改变。2.同时,我们要记录哪些name对应的需要删除,并且除了特定的保留(即type为1的)外。但是,对于同一个name,可能有多个type1的,那么我们希望保留所有type1的吗?题目没有说,但根据题目要求,每次遇到一个type1的,我们只删除其他,也就是说,每个type1的都不删除,这样同一个name下的多个type1的都会被保留。然而,这样逻辑上是不通的:因为如果同一个name有两个type1的,那么第一个type1的会删除第二个(因为第二个是其他),而第二个type1的也会删除第一个(第一个也是其他),结果就是两个都删除了?这显然不合理。所以,我们重新理解:题目要求是“当某一项的type为1时,删除所有与该name相同的其他”,这个“其他”的意思就是除了当前这一项以外的所有同名。那么对于整个数组,我们最终希望的效果是:对于每一个在数组中出现过的name,如果这个name对应的中有type为1的,那么我们就只保留这些type为1的(并且每个都保留),而删除这个name对应的其他所有(即type不为1的)?不对,因为题目说“删除所有与该name相同的其他”,并没有说只保留type1的,而是对于这个type1的,只保留它自己,删除其他同名(包括其他type1的同名)。所以最终每个name最多只能保留一个type1的?不对,因为可能一开始就有多个type1的,但我们在删除过程中可能把它们都删了(互相删除)。为了避免歧义,我们这样处理:我们需要删除所有name出现在“被标记name集合”中,且不是type为1的?不对,因为题目要求是删除其他(包括type为1的同名,只要不是自身)。实际需求应该是:我们要求每个name最多只能保留一个type为1的,并且删除所有其他同名(无论type是多少)。但是题目没有说保留哪一个。所以我们可以这样:对于每个name,只保留第一个出现的type为1的,其他所有同名都删除(包括其他type1的)。这样,同一个name下最多只保留一个type1的。但是,题目描述中并没有说保留哪一个,只说了“当某一项的type为1时,删除所有与该name相同的其他”。所以,如果我们按照顺序执行,那么当遇到第一个type1的(假设name为A)时,会删除后面所有的name为A的(包括后面type1的)。那么后面遇到name为A的type1的时,已经被删除了,所以就不会再执行了。这样,最终每个同名组最多只保留第一个type1的。但是,注意:数组中可能有多个不同的name,每个name组是独立的。所以,我们需要收集所有需要执行删除的name(即出现过type1的name),然后对每个name,我们只保留第一个type1的(但题目没有要求保留第一个,只是要求删除其他,所以如果多个type1的是同一个name,那么只有第一个会保留,后面的都会被删除)。因此,我们可以这样实现:步骤1:构建一个Map,key是name,value是一个数组,包含这个name出现的所有索引(或者我们在遍历时处理)。同时,我们标记这个name是否遇到过type1的。步骤2:遍历数组,对于每个元素,如果当前的type是1,那么:如果这个name还没有被处理过(即第一次遇到这个name的type1),那么我们将这个name标记为“需要删除其他”,并且记录当前这个type1的需要保留。如果这个name已经被标记过了(即之前已经有一个type1的),那么我们就要删除当前这个(因为对于这个name,我们只保留第一个type1的,而当前这个就是多余的,会被删除)。但是,这样我们在第一次遇到一个name的type1时,我们无法知道后面还有没有同名的type1,所以我们需要两次遍历。另一种思路:我们不要按来处理,而是按name组来处理。具体算法:1.第一次遍历:收集每个name对应的,以及这些中是否有type为1的,同时记录第一个出现type为1的或者我们只关心有type1就行,然后我们删除所有其他?注意,我们最终要保留所有的type1的吗?题目描述没有明确,但会导致互相删除,所以我们只能保留一个)。基于以上分析,我决定这样实现:我们最终保留的包括:-所有type不为1的,且其name没有在任何type1的中出现过(即这些name没有被要求删除)。-对于每个出现过type1的name,我们只保留这些name中第一个type为1的(因为后面的同名都会被删除)。所以,步骤:1.首先,我们创建一个Set,用于保存要保留的name对应的第一个type1的的索引(或者我们不需要记索引,而是用一个Map记录每个name的type1的已经出现过了)。2.创建一个数组,用于存放结果(或者我们直接在原数组上删除,但这样需要倒序遍历,防止索引变化)。3.我们需要先遍历一遍,找到每个name对应的第一个type1的,并记录下来(比如用一个Map,key为name,value为第一个type1的索引),同时,对于每个name,我们还需要知道是否遇到了type1的。4.然后再遍历一次,对于每个元素:-如果当前是一个type1的,并且它是该name下第一个type1的,那么保留。-如果当前是一个type1的,但不是第一个(即这个name已经记录过第一个type1的了),那么删除。-如果当前type不是1,但它的name在之前出现过type1的(即该name已经在我们的Map中,表示有第一个type1的),那么删除(因为我们要删除所有其他)。-如果当前type不是1,且它的name没有在Map中出现过(即该name没有出现过type1的),那么保留。所以,我们需要:1.第一次遍历:构建一个Map(name->第一个type1的出现的位置),但实际上我们不需要记录位置,只需要知道哪些name有type1的(并且我们并不需要知道第一个出现的位置,因为后续我们会再遍历去判断第一个)。但为了识别第一个,我们可以用一个Map来记录某个name是否已经遇到了第一个type1的。具体:-创建一个Map:`constnameHasType1=newMap();`//记录每个name是否已经出现过type1的(这个Map的key是name,value是布尔,表示该name已经出现过type1的?但这样不行,因为我们还要保留第一个type1的。实际上,我们只保留第一个type1的,后面的同名(不管type是什么)都不保留。因此,我们需要两个集合:-一个Set:`constnamesWithType1=newSet();`//存放所有出现过type1的的name(不管出现几次,只要出现过一次,就加入这个集合)-一个Map:`constfirstType1IndexPerName=newMap();`//但这里我们其实不需要记录第一个出现的位置,因为我们第二次遍历时,对每个name,只有第一个type1的被保留,后面的都不保留(包括type1的和非type1的都不保留)。不对,我们的保留规则是:对于有type1的name,只保留第一个type1的,其他所有同名都删除。所以,在第一次遍历时,我们需要记录每个name的第一个type1的,但同时,我们在第二次遍历时,需要判断当前是不是某个name的第一个type1的,所以我们需要记录第一个type1的的标识(比如它的索引),或者我们可以改变一下:我们用一个Map,key为name,value为{firstType1Item:item},但我们只记索引,然后我们在第一次遍历时,遇到一个type1的,并且它的name还没有被记录过,那么我们就记录这个索引(然后第二次遍历时,我们保留这个索引的,而删除其他同名)。但是这样第二次遍历时,我们需要根据name去Map中取出第一个type1的索引,然后判断当前索引是否等于这个索引,相等才保留(但这样需要记录索引)。另一种更简单的思路:我们遍历两次,第一次只记录每个name出现的第一个type1的的索引(用一个Map:name->index),但注意,同一个name可能多次出现,我们只记录第一个type1的的索引。第二次遍历时,对于每一项:如果该的name不在这个Map的key中(说明这个name没有出现过type1的),那么保留。如果该的name在Map的key中,那么判断当前的索引是否等于Map中存的索引(即第一个type1的的索引),相等则保留,不相等则删除。但是,这样有一个问题:可能一个name有多个type1的,我们只记录了第一个type1的的索引,那么后面type1的和所有非type1的同名都会被删除(因为它们的索引不等于第一个type1的索引)。这样正好满足:只保留第一个type1的,删除其他所有同名。但是,注意:也有可能一个name有非type1的出现在第一个type1的之前。那么这些在第一个type1之前的非type1应该被删除吗?根据题目,当我们遇到第一个type1(假设在索引i处)时,我们会删除所有其他(不管是在i之前还是之后)。所以,在i之前的同名(即使是非type1)也应该删除。但按照上述方法,我们在第一次遍历记录第一个type1的索引时,我们只记录第一个type1(可能并不是这个name的第一个,而是这个name的第一个type1的)。在第二次遍历时,对于这个name的所有(除了第一个type1的),无论它们在第一个type1之前还是之后,我们都删除。因此,我们需要:第一次遍历:构建一个Map,key为name,value为第一个type1的的索引(注意:我们只记录第一个type1的索引,同一个name后面再出现type1的我们不更新这个Map)。同时,我们在第一次遍历时,我们不知道哪个name的哪个type1是第一个,所以我们需要:初始化:nameToFirstType1IndexMap=newMap()遍历数组,对于每一项:如果当前的type为1,并且这个name还没有在nameToFirstType1IndexMap中记录,那么就将这个name的索引记录到Map中(注意:同一个name可能有多个type1,但我们只记录第一次出现的type1的索引)。第二次遍历:创建一个新数组或者直接在原数组上操作(建议使用新数组以免混淆)。遍历数组,对每一项:如果当前的name不在nameToFirstType1IndexMap中(即该name没有type1出现过),则保留该。如果当前的name在nameToFirstType1IndexMap中:则检查当前的索引是否等于nameToFirstType1IndexMap中存储的索引(即第一个type1的索引),如果是,保留;否则,删除(即不加入新数组)。这个方案可以满足:对于每个name,只保留第一个type1的(如果存在的话),而删除该name的所有其他(不管type是什么,也不管出现顺序)。但是,注意:如果一个name没有type1的,那么该name的所有都会被保留。所以,代码实现:```javascriptfunctionfilterArray(arr){//创建一个Map:key为name,value为第一个type为1的的索引constfirstType1IndexMap=newMap();//第一次遍历:找到每个name的第一个type为1的for(leti=0;i< arr.length;i++){constitem=arr[i];if(item.type===1){//如果这个name还没有记录过第一个type1的索引,则记录if(!firstType1IndexMap.has(item.name)){firstType1IndexMap.set(item.name,i);}}}//第二次遍历:构建结果数组constresult=[];for(leti=0;i< arr.length;i++){constitem=arr[i];//如果当前的name没有在firstType1IndexMap中出现过(说明该name没有type1),直接保留if(!firstType1IndexMap.has(item.name)){result.push(item);}else{//如果当前的name有type1,那么只保留第一个type1(即索引等于记录的那个索引)if(i===firstType1IndexMap.get(item.name)){result.push(item);}//否则,跳过(即不保留)}}returnresult;}```测试:假设数组为:constarr=[{name:'A',type:0},{name:'A',type:1},//这是name为A的第一个type1(索引为1){name:'A',type:1},{name:'B',type:1},//这是name为B的第一个type1(索引为3){name:'B',type:0},{name:'C',type:0}];结果应该:name为A:保留索引1的(第一个type1),删除索引0和2的(即使索引0在第一个type1之前,也要删除)。name为B:保留索引3的(第一个type1),删除索引4的。name为C:没有type1,所以保留。所以结果数组:[{name:'A',type:1},{name:'B',type:1},{name:'C',type:0}]但是,注意:第一个type1可能在数组的任何位置。例如:constarr=[{name:'A',type:1},//索引0:name为A的第一个type1{name:'A',type:0},//删除{name:'B',type:0},//保留(因为B没有type1?不对,下面有一个type1的B){name:'B',type:1}//索引3:name为B的第一个type1,所以上面的B?0应该保留吗?不对,我们对于B,第一次遇到type1是在索引3,那么在索引3之前的B(索引2处不是B,而是索引3才是B的第一个type1)?但是,索引2是B?0,是B的一项,所以也会被删除?不对,我们第一次遍历时,对于B,我们在索引3发现type1的,然后记录索引3。第二次遍历时,对于B的(索引3)保留,而其他索引位置(比如索引2)的B,如果也是B,那么就会被删除?但是索引2的name是'B'吗?上面索引2的是name为'B',type为0。所以它会被删除吗?注意在第二次遍历时,索引2的name为'B',并且firstType1IndexMap中会有'B'(索引3),当前索引2不等于3,所以不保留。所以索引2的B?0会被删除。因此,结果数组应为:[{name:'A',type:1},{name:'B',type:1}]另外,C呢?这里没有C。所以上述代码符合要求。但是,还有一种情况:同一个name,可能有多个type1的,且这些type1的并不连续?没关系,我们只保留第一个,其他都不保留。但是,注意:这个算法删除了在第一个type1之前的同名(即使是非type1),同时也删除了之后的同名(包括type1和非type1),这符合题目要求(当某一项是type1时,删除所有其他同名)。但是,题目中要求的是“当某一项的type为1时”,我们只删除其他,但这里我们实际上是对于有type1的name,只保留第一个type1的,其他所有同名(不管type)都删除。这样,如果某个name有多个type1的,那么只有第一个被保留。而题目并没有说只保留第一个,所以这里可能存在歧义:题目要求是对每一个type1的都执行一次删除操作,但我们的算法效果是保留第一个type1的,删除了其他所有同名(包括其他type1的)。根据题目的描述,这个效果应该满足:因为每个type1的都执行了删除所有其他同名的操作,第一个type1的执行后,删除了后面的所有同名(包括其他type1的),所以后面的type1的已经被删除了,因此它们就不会再被执行删除操作(因为已经被移除了)。所以最终只有第一个type1的被保留,其他同名都被删除。所以符合。因此,我们按照这个算法实现。但是,注意:如果数组很大,两次遍历也是O(n),效率可以接受。另外,题目要求是删除所有其他,包括在第一个type1之前的同名(如果有的话),所以我们的算法也做到了。因此,代码实现如上。如果题目要求保留所有type1的(即不互相删除),那么题目描述应该改为:删除所有name相同的type不为1的。但题目明确说“删除所有与该name相同的其他”,所以包括type1的其他。所以,我们按上述算法实现即可。</think> 要在数组中实现"当某一项的 `type` 为 1 时,删除所有与该 `name` 相同的其他"的功能,可以通过以下步骤实现: ### 实现方法 ```javascript function filterArray(arr) { // 1. 记录所有需要被删除的name集合 const namesToDelete = new Set(); // 2. 找出所有type为1的,并记录它们的name arr.forEach(item => { if (item.type === 1) { namesToDelete.add(item.name); } }); // 3. 使用reduce过滤数组 return arr.reduce((result, currentItem) => { const isSpecialType = currentItem.type === 1; const isNameMarked = namesToDelete.has(currentItem.name); if (!isNameMarked) { // 情况1: 非标记name的直接保留 result.push(currentItem); } else if (isSpecialType) { // 情况2: 是type=1的,保留但移除name标记 result.push(currentItem); namesToDelete.delete(currentItem.name); } // 情况3: 同名非type=1的会被跳过(被删除) return result; }, []); } ``` ### 算法说明 1. **收集特殊** 使用 `Set` 记录所有 `type === 1` 的 `name` 2. **一次遍历处理** 使用 `reduce` 方法遍历数组时,分三种情况处理: - **非特殊名称**:直接保留(`name` 不在删除集合中)[^1] - **标记名称的 type=1 **:保留该并**从删除集合中移除该 `name`** - **标记名称的非 type=1 **:跳过(被删除) 3. **关键机制** - 第一个遇到的 `type=1` 会将其 `name` 从删除集合中移除 - 后续所有同名(无论 `type` )都会被跳过 - 同名非特殊的删除是隐式的(通过不加入结果数组) ### 使用示例 ```javascript const data = [ { id: 1, name: "A", type: 0 }, { id: 2, name: "B", type: 1 }, // 触发删除 { id: 3, name: "C", type: 0 }, { id: 4, name: "B", type: 0 }, // 被删除 { id: 5, name: "D", type: 1 }, // 触发删除 { id: 6, name: "B", type: 2 }, // 被删除 { id: 7, name: "D", type: 0 } // 被删除 ]; console.log(filterArray(data)); /* 输出: [ { id: 1, name: "A", type: 0 }, { id: 2, name: "B", type: 1 }, { id: 3, name: "C", type: 0 } ] */ ``` ### 算法特点 1. **时间复杂度**:$O(n)$ - 单次遍历数组完成所有操作 2. **空间复杂度**:$O(k)$ - `k` 为特殊的 `name` 数量 3. **执行顺序敏感** - 保留第一个遇到的 `type=1` - 删除后续所有同名(包括其他 `type=1` )[^2] 4. **纯函数实现** - 不修改原数组,返回新数组 ### 处理流程图 ```mermaid graph TD Start[开始遍历] --> CheckItem{检查当前} CheckItem --> |name不在删除集| Keep[直接保留] CheckItem --> |name在删除集且type=1| KeepRemove[保留并移除此name] CheckItem --> |name在删除集且type≠1| Skip[跳过删除] Keep --> Next KeepRemove --> Next Skip --> Next Next{还有下一项?} --> |是| CheckItem Next --> |否| End[返回结果] ``` 这个方法高效解决了问题,同时保持代码简洁易读。关键在于利用 `Set` 的快速查找特性,以及通过修改 `Set` 内容动态控制后续的保留逻辑。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值