繁体   English   中英

计算数组中的唯一值

[英]count unique values in array

我很难计算数组中唯一值的数量。 我不能真正使用 [i+1] 来评估,因为它可能会将第 i+1 个 position 之后的任何值计算为唯一值,而实际上稍后在数组中有重复值(参见 28 和 29)...任何想法? 非常感谢您的帮助!

[28, 28, 29, 30, 01, 28, 02, 29]

function CalcDiscretePeriods(const Arr: Array):Integer;
var
   i: Integer;
begin
   for i:= 0 to High(Arr)-1 do
   begin
       if (Arr[i]<>Arr[i+1]) then countD:= countD + 1;
   end;
end;

(我正在使用 MacOSX,免费的 Pascal 编译器版本 2.6.4 [2014/02/26] for i386 如果相关的话)。

根据个人经验,您可以使用以下算法来成功计算数组中的唯一值。

您将需要第二个数组,例如“ uniqueArray”(理想的是像数据结构这样的哈希图比数组要好)

1)从现有数组'Arr'中的每个元素'i'从i = 0迭代到High(Arr)-1

2)对于每个“ i”, 仅当 uniqueArr尚未具有该值时,才将此值复制到第二个数组“ uniqueArray”中(需要uniqueArr中每个元素的循环)。

3)成功复制后,增加计数。

恐怕我不熟悉提供任何实际示例的语言。

一个特别慢但 memory 有效的方法是遍历数组两次。 以下是符合 Extended Pascal(ISO 标准 10206)的摘录:

type
    integerNonNegative = 0..maxInt;

{ returns the number of unique values in `list` }
function discretePeriods(
        protected list: array[lowerBound..upperBound: integer] of integer
    ): integerNonNegative;
    { determines whether `reference` occurs only once in `list` }
    function isUnique(protected reference: type of list[lowerBound]): Boolean;
        { counts the number of occurences of a `reference` value }
        function occurences: integerNonNegative;
        var
            i: type of lowerBound;
            n: integerNonNegative value 0;
        begin
            for i := lowerBound to upperBound do
            begin
                if list[i] = reference then
                begin
                    n := n + 1;
                end;
            end;
            occurences := n;
        end;
    begin
        isUnique := occurences = 1;
    end;
var
    i: type of lowerBound;
    uniqueValues: integerNonNegative value 0;
begin
    for i := lowerBound to upperBound do
    begin
        if isUnique(list[i]) then
        begin
            uniqueValues := uniqueValues + 1;
        end;
    end;
    discretePeriods := uniqueValues;
end;

另一种更快但内存密集型的方法是,正如已经建议的那样,分析步骤计算步骤分开。 在 Extended Pascal 中,这可能如下所示:

const
    integersMaximum = 4194303;

type
    integerNonNegative = 0..maxInt;
    integersRange = -integersMaximum..+integersMaximum;
    {$setLimit=8388608}{ only in GPC }
    integers = set of integersRange value [];

{ returns the number of unique values in `list` }
function discretePeriods(
        protected list: array[lowerBound..upperBound: integer] of integersRange
    ): integerNonNegative;
var
    population: integers;

    procedure populate;
    var
        i: type of lowerBound;
    begin
        { transform ordered list to “unordered” `set` }
        for i := lowerBound to upperBound do
        begin
            population := population + [list[i]];
        end;
    end;

    function duplicates: integers;
    var
        i: type of lowerBound;
        m: integers;
    begin
        for i := lowerBound to upperBound do
        begin
            { construct a set of all values that appear more than once }
            if not (list[i] in population) then
            begin
                m := m + [list[i]];
            end;
            { at any rate remove the current item from `population` }
            population := population - [list[i]];
        end;
        duplicates := m;
    end;
var
    n: integerNonNegative;
begin
    populate;
    { calculation step }
    n := card(population);
    discretePeriods := n - card(duplicates);
end;

最后还是要看你的具体使用场景。 可能您(最终)无论如何都需要对数组进行排序,因此Rudy Velthuis建议的方法可能最适合您。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM