Java method for checking if one item in list is in another list of items (sort of like a VLOOKUP in excel)?

huangapple go评论120阅读模式
英文:

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&lt;Integer&gt; masterList = Arrays.asList(122, 123, 124, 155, 621, 982);
List&lt;Integer&gt; list1 = Arrays.asList(122, 124, 155, 331, 982);
List&lt;Integer&gt; list2 = Arrays.asList(122, 124, 444);
List&lt;Integer&gt; list3 = Arrays.asList(2, 122, 123, 124, 133, 155, 332, 621, 667, 982);

// 我猜每个列表都可以单独存在,但是为了我的目的,这些列表都在一个列表中,所以:

List&lt;List&lt;Integer&gt;&gt; lists = new ArrayList&lt;&gt;();
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&lt;Integer&gt; masterList = Arrays.asList(122, 123, 124, 155, 621, 982);
List&lt;Integer&gt; list1 = Arrays.asList(122, 124, 155, 331, 982);
List&lt;Integer&gt; list2 = Arrays.asList(122, 124, 444);
List&lt;Integer&gt; 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&lt;List&lt;Integer&gt;&gt; lists = new ArrayList&lt;&gt;();
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&lt;List&lt;String&gt;&gt; as long as 331(#N/A) us not an integer value.

List&lt;List&lt;String&gt;&gt; checkedList = lists.stream()
        .map(list -&gt; list.stream()
                         .map(i-&gt; masterList.contains(i) ? i + &quot;&quot; : i + &quot;(#N/A)&quot;)
                         .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&lt;Map&lt;Boolean, List&lt;Integer&gt;&gt;&gt; map = lists.stream()
       .map(list -&gt; 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&lt;List&lt;AbstractMap.SimpleEntry&lt;Integer, Boolean&gt;&gt;&gt; res = 
   lists.stream()
        .map(e -&gt; e.stream()
                   .map(ee -&gt; new AbstractMap.SimpleEntry&lt;&gt;(ee, masterList.contains(ee)))
                   .collect(Collectors.toList()))
        .collect(Collectors.toList());

Here, transform every Integer into AbstractMap.SimpleEntry&lt;Integer, Boolean&gt; 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&lt;Integer, String&gt; also and map as

ee -&gt; new AbstractMap.SimpleEntry&lt;&gt;(ee, masterList.contains(ee)? &quot;(N/A)&quot; : null)

And to sort a List&lt;AbstractMap.SimpleEntry&lt;Integer, Boolean&gt;&gt; by it's Integer part only.

Collections.sort(list, Comparator.comparing(e -&gt; e.getKey()));

huangapple
  • 本文由 发表于 2020年9月29日 14:30:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/64114068.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定