英文:
Java method for checking if one item in list is in another list of items (sort of like a VLOOKUP in excel)?
问题
假设我们有一组整数的列表,形式如下:[list1,list2,list3],基本上是List<List<Integer>>。然后假设我们有主列表masterList,它只是List<Integer>。是否有一种方法可以检查List<List<Integer>>中的每个列表,并且对于每个列表中的每个值,如果该值或项在主列表中,则保持不变,但如果不在主列表中,则应在其旁边添加"(N/A)"。例如:
List<Integer> masterList = Arrays.asList(122, 123, 124, 155, 621, 982);
List<Integer> list1 = Arrays.asList(122, 124, 155, 331, 982);
List<Integer> list2 = Arrays.asList(122, 124, 444);
List<Integer> list3 = Arrays.asList(2, 122, 123, 124, 133, 155, 332, 621, 667, 982);
// 我猜每个列表都可以单独存在,但是为了我的目的,这些列表都在一个列表中,所以:
List<List<Integer>> lists = new ArrayList<>();
lists.add(list1);
lists.add(list2);
lists.add(list3);
因此,如果我们要将lists中的每个列表与masterList进行比较,那么最终结果应该是一组列表,但每个列表都将具有已更新的值,指示它们是否在主列表中。因此,为了方便起见,我使用伪代码来表示:
list1 = [122, 124, 155, 331(#N/A), 982(#N/A)]
list2 = [122, 124, 444(#N/A)]
list3 = [2(#N/A), 122, 123, 124, 133(#N/A), 155, 332(#N/A), 621(#N/A), 667(#N/A), 982(#N/A)]
然后我猜它们都会再次放入一个列表中,所以,lists.add(list1, list2, list3)。
我尝试编写这个代码,但失败了,而且我尝试想出的一些解决方案的时间/空间复杂度非常糟糕。假设涉及的每个列表都是排序的、唯一的,且不必具有相同的大小。
必须确保原始列表的元素类型是Integer,以便对其进行排序,但我知道最终需要有一个新列表,其中包含三个新列表,最终的元素类型不再是Integer,而是String。这有点类似于在Excel中使用VLOOKUP比较3列和1列。如果有人能够提供一个解决方案,我会非常感激!谢谢!
英文:
Say we have a list of a list of integers. What that would look like is [list1, list2, list3], basically List<List<Integer>>. Then assume we have the master list masterList which is just List<Integer>. Is there a way to check each list in List<List<Integer>> and for each value in each list, if the value, or item, is in the master list, then leave as is, but if it is not in the master list then there should be a "(N/A)" next to it. So example:
List<Integer> masterList = Arrays.asList(122, 123, 124, 155, 621, 982);
List<Integer> list1 = Arrays.asList(122, 124, 155, 331, 982);
List<Integer> list2 = Arrays.asList(122, 124, 444);
List<Integer> list3 = Arrays.asList(2, 122, 123, 124, 133, 155, 332, 621, 667, 982);
// I guess each list could be on its own, but for my purposes the lists are in a list, so:
List<List<Integer>> lists = new ArrayList<>();
lists.add(list1);
lists.add(list2);
lists.add(list3);
So if we were to compare each list in lists to the masterList, then the end result should be a list of lists but each list will have updated values indicating if they are in the master list or not, so for pseudo-code ease sakes:
list1 = [122, 124, 155, 331(#N/A), 982(#N/A)]
list2 = [122, 124, 444(#N/A)]
list3 = [2(#N/A), 122, 123, 124, 133(#N/A), 155, 332(#N/A), 621(#N/A), 667(#N/A), 982(#N/A)]
and then I guess they would all be in lists again, so, lists.add(list1, list2, list3).
I tried coding this but failed, and some solutions i tried coming up with had really bad time/space complexity. It's assumed that every list involved is sorted, unique, and does not have to be the same size.
It is necessary that the original list is of Integer type so it could be sorted, but I know that in the end there needs to be a new list holding 3 new lists that in the end are of String type, not Integer type anymore. This is sort of like comparing 3 columns to 1 column using VLOOKUP in Excel. If anyone could help out with a solution, you have my blessings!! Thank you!
答案1
得分: 2
解决方案
只需对列表中的每个数字使用Stream::map
。使用三元运算符,将其转换为原始值或带有(#N/A)
前缀的新字符串值。注意,只要331(#N/A)
不是整数值,新返回的结构就是List<List<String>>
。
List<List<String>> checkedList = lists.stream()
.map(list -> list.stream()
.map(i -> masterList.contains(i) ? i + "" : i + "(#N/A)")
.collect(Collectors.toList()))
.collect(Collectors.toList());
checkedList.forEach(System.out::println); // 输出如下结果
[122, 124, 155, 331(#N/A), 982] [122, 124, 444(#N/A)] [2(#N/A), 122, 123, 124, 133(#N/A), 155, 332(#N/A), 621, 667(#N/A), 982]
建议
然而,结果有些可疑,您失去了对数字的便捷处理,数据看起来相当混乱。我更愿意根据元素在masterList
中的存在将列表拆分成两部分。使用Collectors.partitioningBy
:
List<Map<Boolean, List<Integer>>> map = lists.stream()
.map(list -> list.stream()
.collect(Collectors.partitioningBy(masterList::contains)))
.collect(Collectors.toList());
map.forEach(System.out::println); // 输出如下结果
{false=[331], true=[122, 124, 155, 982]} {false=[444], true=[122, 124]} {false=[2, 133, 332, 667], true=[122, 123, 124, 155, 621, 982]}
false
表示这些元素不在masterList
中。true
则表示相反。您可以在JDoodle上进行验证。
英文:
Solution
Simply use Stream::map
for each number present in the list. Using the ternary operator, you transform it either to self or to a new String value with (#N/A)
prefix. Note the newly returned structure is List<List<String>>
as long as 331(#N/A)
us not an integer value.
List<List<String>> checkedList = lists.stream()
.map(list -> list.stream()
.map(i-> masterList.contains(i) ? i + "" : i + "(#N/A)")
.collect(Collectors.toList()))
.collect(Collectors.toList());
checkedList.forEach(System.out::println); // results in the output below
> [122, 124, 155, 331(#N/A), 982]
> [122, 124, 444(#N/A)]
> [2(#N/A), 122, 123, 124, 133(#N/A), 155, 332(#N/A), 621, 667(#N/A), 982]
Suggestion
However, the result is a bit questionable and you lose comfortable handling with numbers and the data look quite dirty. I'd rather split the lists into two by the element's presence in the masterList
. Use Collectors.partitioningBy
:
List<Map<Boolean, List<Integer>>> map = lists.stream()
.map(list -> list.stream()
.collect(Collectors.partitioningBy(masterList::contains)))
.collect(Collectors.toList());
map.forEach(System.out::println); // results in the output below
> {false=[331], true=[122, 124, 155, 982]}
> {false=[444], true=[122, 124]}
> {false=[2, 133, 332, 667], true=[122, 123, 124, 155, 621, 982]}
The false
indicates these not present in masterList
. The true
represents otherwise. Feel free to check it out at JDoodle.
答案2
得分: 1
你可以使用整数和布尔值对的列表,然后按对中的整数部分对列表进行排序。用于配对的方法可以使用 AbstractMap.SimpleEntry
。
List<List<AbstractMap.SimpleEntry<Integer, Boolean>>> res =
lists.stream()
.map(e -> e.stream()
.map(ee -> new AbstractMap.SimpleEntry<>(ee, masterList.contains(ee)))
.collect(Collectors.toList()))
.collect(Collectors.toList());
在这里,通过使用 contains()
方法检查列表的每个元素是否存在于 masterList
中,将每个 Integer
转换为 AbstractMap.SimpleEntry<Integer, Boolean>
。
我猜你只是查看了 (N/A)
部分,如果你想直接为元素存储字符串,你也可以使用 AbstractMap.SimpleEntry<Integer, String>
,然后进行映射:
ee -> new AbstractMap.SimpleEntry<>(ee, masterList.contains(ee) ? "(N/A)" : null)
要对 List<AbstractMap.SimpleEntry<Integer, Boolean>>
按其整数部分进行排序,可以使用以下方法:
Collections.sort(list, Comparator.comparing(e -> e.getKey()));
英文:
You can use List of Integer, Boolean pair per list then you can sort the list by Integer part of pair. For pairing you can use AbstractMap.SimpleEntry
.
List<List<AbstractMap.SimpleEntry<Integer, Boolean>>> res =
lists.stream()
.map(e -> e.stream()
.map(ee -> new AbstractMap.SimpleEntry<>(ee, masterList.contains(ee)))
.collect(Collectors.toList()))
.collect(Collectors.toList());
Here, transform every Integer
into AbstractMap.SimpleEntry<Integer, Boolean>
by checking every element of list exists in masterList
using contains()
method
I guess (N/A)
view part only, if you want directly store String for element you can use AbstractMap.SimpleEntry<Integer, String>
also and map as
ee -> new AbstractMap.SimpleEntry<>(ee, masterList.contains(ee)? "(N/A)" : null)
And to sort a List<AbstractMap.SimpleEntry<Integer, Boolean>>
by it's Integer
part only.
Collections.sort(list, Comparator.comparing(e -> e.getKey()));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论