如何打印数组中两个参数相同对象的值之和

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

How to print the sum of values from the same objects of 2 parameter in array

问题

public class Dollars
{
    private String name;
    private int dollars;
    
    public Dollars(String name, int dollars)
    {
        this.name = name;
        this.dollars = dollars;
    }

    public String getName()
    {
        return name;
    }
    
    public int getChange()
    {
        return dollars;
    }
}
public class TestDollars 
{
    
    public static void displayArray(Dollars[] dol)
    {
        int sum = 0;
        for (int n = 0; n < dol.length; n++)
        {
            sum = dol[n].getChange();
            
            for (int m = n + 1; m < dol.length; m++)
            {
                if (dol[n].getName().equals(dol[m].getName()))
                {
                    sum += dol[m].getChange();
                    dol[m].setName("");  // Set name to empty to mark as processed
                }
            }
            
            if (!dol[n].getName().equals("")) {
                System.out.printf("%s -- %d\n", dol[n].getName(), sum);
            }
        }
    }
    
    public static void main(String[] args)
    {
        // Test with 5 records
        Dollars[] dollarsArr = new Dollars[5];
        dollarsArr[0] = new Dollars("john", 10);
        dollarsArr[1] = new Dollars("peter", 12);
        dollarsArr[2] = new Dollars("sam", 5);
        dollarsArr[3] = new Dollars("alvin", 16);
        dollarsArr[4] = new Dollars("peter", 30);
        displayArray(dollarsArr);
    }
}
英文:

I am learning java and I hit into a snag as I could not figure out my loop or array.
I have an array which contains class objects containing a string and integer parameters, in my code, it will be name and dollars.

I am trying to print out the array in which, if there is a same name, it is to print once and with the sum of the dollars (from the same name).

In my Dollars.java

public class Dollars
{
private String name;
private int dollars;
public dollars (String name, int dollars)
{
this.name = name;
this.dollars = dollars;
}
public String getName()
{
return name;
}
public int getChange()
{
return dollars;
}
}

In my main file/ TestDollars.java

public class TestDollars 
{
public static void displayArray(Dollars[] dol)
{
int sum = 0;
for (int n=0; n&lt;dol.length; n++)
{
for (int m=n+1; m&lt;dol.length; m++)
{
if (dol[n].getName().equals(dol[m].getName()))
{
//                    System.out.printf(&quot;%s -- %d\n&quot;, dol[n].getName(), dol[n].getChange());
sum = dol[n].getChange() + dol[m].getChange();
System.out.printf(&quot;%s -- %d\n&quot;, dol[m].getName(), sum);
break;
}
}
System.out.printf(&quot;%s -- %d\n&quot;, dol[n].getName(), dol[n].getChange());     
}
}
public static void main(String[] args)
{
// Test with 5 records
Dollars[] dollarsArr = new Dollars[5];
dollarsArr[0] = new Dollars(&quot;john&quot;, 10);
dollarsArr[1] = new Dollars(&quot;peter&quot;, 12);
dollarsArr[2] = new Dollars(&quot;sam&quot;, 5);
dollarsArr[3] = new Dollars(&quot;alvin&quot;, 16);
dollarsArr[4] = new Dollars(&quot;peter&quot;, 30);
displayArray(dollarsArr);
}
}

Irregardless where I place my print statement in the displayArray, the record 'peter' will gets printed twice.

Expected output:

john -- 10
peter -- 42
sam -- 5
alvin -- 16

Current output:

john -- 10
peter -- 42
peter -- 12
sam -- 5
alvin -- 16
peter -- 30

答案1

得分: 4

你想按名称对列表进行分组,请使用JAVA 8+ API Stream和收集器group by

public static void displayArray(Dollars[] dol) {
    Stream.of(dol)
        // 按名称分组
        .collect(Collectors.groupingBy(Dollars::getName))
        .entrySet().stream()
        // 收集名称和计算总和的映射
        .collect(Collectors.toMap(x -> {
            int total = x.getValue().stream().mapToInt(Dollars::getChange).sum();
            return new Dollars(x.getKey(), total);
        }, Map.Entry::getValue))
        // 打印
        .forEach((dollarsTotal, vals) -> {
            System.out.println(dollarsTotal.getName() + " -- " + dollarsTotal.getChange());
            // 奖励:显示交易:
            for (Dollars transaction : vals) {
                System.out.println(" \t " + transaction.getName() + " add  -- " + transaction.getChange());
            }
        });
}

如果你只想要值,可以收集键集合

Set<Dollars> groupedByName = Stream.of(dol)
    // 按名称分组
    .collect(Collectors.groupingBy(Dollars::getName))
    .entrySet().stream()
    // 收集名称和计算总和的映射
    .collect(Collectors.toMap(x -> {
        int total = x.getValue().stream().mapToInt(Dollars::getChange).sum();
        return new Dollars(x.getKey(), total);
    }, Map.Entry::getValue)).keySet();
英文:

You want to group your list by name, please use JAVA 8+ API Stream and the collector group by

public static void displayArray(Dollars[] dol)
    {
       Stream.of(dol)
               // Group by name
               .collect(Collectors.groupingBy(Dollars::getName))
                .entrySet().stream()
               // Collect a map name and calculate the sum
               .collect(
                    Collectors.toMap(x -&gt; {
                    int total= x.getValue().stream().mapToInt(Dollars::getChange).sum();
                    return new Dollars(x.getKey(),total);
                }, Map.Entry::getValue))
               // Print
               .forEach((dollarsTotal, vals) -&gt; {
                    System.out.println(dollarsTotal.getName()+ &quot; -- &quot;+ dollarsTotal.getChange());
                    // Bonus : Display transactions :
                    for(Dollars transaction : vals)
                    {
                        System.out.println(&quot; \t &quot;+transaction.getName() + &quot; add  -- &quot; + transaction.getChange());
                    }
       });
    }

If you want only the values you can collect the keyset

Set&lt;Dollars&gt; groupedByName = Stream.of(dol)
               // Group by name
               .collect(Collectors.groupingBy(Dollars::getName))
                .entrySet().stream()
               // Collect a map name and calculate the sum
               .collect(
                        Collectors.toMap(x -&gt; {

                    int total= x.getValue().stream().mapToInt(Dollars::getChange).sum();
                    return new Dollars(x.getKey(),total);
                }, Map.Entry::getValue)).keySet();

答案2

得分: 3

其他答案指导您修复了您的代码(但它们需要更多的工作来避免重复计算)。

您可以通过使用数据结构(比如映射)来聚合结果,将时间复杂度从 O(n2) 降低到 O(n)(同时使代码更简洁)。

让我们创建一个 Map<String, Integer> 来将姓名映射到该姓名的总金额。

Map<String, Integer> result = new HashMap<>();
for (int i = 0; i < dol.length; i++) {
    if (!result.containsKey(dol[i].getName())) { // 第一次遇到姓名
        result.put(dol[i].getName(), dol[i].getChange());
    } else {
         // 将当前变化值添加到已有的总和中
         int sumSoFar = result.get(dol[i].getName());
         result.put(dol[i].getName(), sumSoFar + dol[i].getChange());
    }
}
System.out.println(result);

结果为:

{peter=42, alvin=16, john=10, sam=5}

您可以使用 Mapmerge 方法简化上述代码,如下所示:

for (Dollars dollars : dol) {
    result.merge(dollars.getName(), dollars.getChange(), Integer::sum);
}

第三个参数是一个 BiFunction,它将旧值和新值相加(迄今累积的总和和当前变化值)。当作为 lambda 表达式编写时,Integer::sum 可以写成 (sumSoFar, currentChange) -> sumSoFar + currentChange


使用流式编程的方式是使用 Collectors.groupingByCollectors.summingInt

Arrays.stream(dol)
        .collect(Collectors.groupingBy(Dollars::getName, Collectors.summingInt(Dollars::getChange)));
英文:

The other answer guides you on fixing your code (Buy they require more work to avoid double counting).

You can reduce the time complexity from O(n<sup>2</sup>) to O(n) (and make it simpler) by having a data structure (like a map) to aggregate the result.

Let us create a Map&lt;String, Integer&gt; to map a name to the total dollars for that name.

Map&lt;String, Integer&gt; result = new HashMap&lt;&gt;();
for (int i = 0; i &lt; dol.length; i++) {
if (!result.containsKey(dol[i].getName())) { //first time you encounter a name
result.put(dol[i].getName(), dol[i].getChange());
} else {
//add the current change to the already existing sum
int sumSoFar= result.get(dol[i].getName());
result.put(dol[i].getName(), sumSoFar + dol[i].getChange());
}
}
System.out.println(result);

Result is,

{peter=42, alvin=16, john=10, sam=5}

You can simplify the above code using Map's merge method as:

for (Dollars dollars : dol) {
result.merge(dollars.getName(), dollars.getChange(), Integer::sum);
}

The third argument is a BiFunction which sums up the old value and new value (the sum accumulated so far and the current change value). When written as a lambda expression, Integer::sum can be written as (sumSoFar, currentChange) -&gt; sumSoFar + currentChange.


A stream evangelist way would be to use Collectors.groupingBy and Collectors.summingInt.

Arrays.stream(dol)
.collect(Collectors.groupingBy(Dollars::getName, Collectors.summingInt(Dollars::getChange)));

答案3

得分: 1

在遍历数组时,将每个非空数组元素的change赋值给变量,例如sum,然后将后续重复元素的change添加到其中。确保在发现重复元素的索引处赋值为null,以防止它们再次计数。这也意味着在对数组元素执行任何操作之前,您必须执行null检查。在完成对重复元素的整个数组的检查后,打印sum的值。

public static void displayArray(Dollars[] dol) {
    for (int n = 0; n < dol.length; n++) {
        if (dol[n] != null) {
            int sum = dol[n].getChange();
            for (int m = n + 1; m < dol.length; m++) {
                if (dol[m] != null && dol[n].getName().equals(dol[m].getName())) {
                    sum += dol[m].getChange();
                    dol[m] = null;
                }
            }
            System.out.printf("%s -- %d\n", dol[n].getName(), sum);
        }
    }
}

输出:

john -- 10
peter -- 42
sam -- 5
alvin -- 16

注意: 如果要保持原始数组不变,在方法displayArray中传递数组的克隆,而不是传递数组本身,如下所示:

displayArray(dollarsArr.clone());
英文:

While navigating the array, assign the change of each non-null array-element to a variable e.g. sum and then add the change of the succeeding duplicate elements to it. Make sure to assign null to the indices where duplicate elements are found so that they can not be counted again. It also means that you will have to perform a null check before performing any operation on the array elements. Print the value of sum once you have checked the complete array for duplicate elements.

public static void displayArray(Dollars[] dol) {
for (int n = 0; n &lt; dol.length; n++) {
if (dol[n] != null) {
int sum = dol[n].getChange();
for (int m = n + 1; m &lt; dol.length; m++) {
if (dol[m] != null &amp;&amp; dol[n].getName().equals(dol[m].getName())) {
sum += dol[m].getChange();
dol[m] = null;
}
}
System.out.printf(&quot;%s -- %d\n&quot;, dol[n].getName(), sum);
}
}
}

Output:

john -- 10
peter -- 42
sam -- 5
alvin -- 16

Note: If you want to keep the original array intact, pass the clone of the array to the method, displayArray instead of passing the array itself as shown below:

displayArray(dollarsArr.clone());

huangapple
  • 本文由 发表于 2020年10月10日 16:23:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/64291427.html
匿名

发表评论

匿名网友

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

确定