Если у меня есть массив, состоящий из чисел, скажем,

A = [1.3, 2.2, 2.3,4.2, 5.1, 3.2, 5.3, 3.3, 2.1,1.1, 5.2, 3.1]

Я хотел бы извлечь числа, которые только там, где целое число находится в массиве и .1, .2 и .3 после. Например, я не хотел бы включать 1 в моем новом массиве, потому что 1.2 не существует в A. Я хотел бы включить 5, хотя, поскольку 5.1.5.2 и 5.3 находятся в A. Как я могу сделать это? Ответы MatLab или Python приняты!

РЕДАКТИРОВАТЬ ** Спасибо. Теперь я понимаю, что, возможно, я задал неправильный вопрос, вместо того, чтобы печатать целые числа с десятичными числами .1, .2, .3 Я хочу, чтобы конечный массив состоял из чисел с плавающей запятой из A, но только тех, у которых есть оба .1, .2, .3 за тем же целым числом. Сожалею!

2
sn3jd3r 7 Янв 2017 в 14:33

6 ответов

Лучший ответ

В MATLAB (возможно, не лучший алгоритм):

clc; clear;

tolerance = 10^(-15);
% Tolerance is useful in order to compare arrays, because the "==" operator
% can lean to wrong results.

% The fractional parts we are interested in.
desirable_list = [0.1 0.2 0.3];

% Because we are going to work with ordered lists, we order the
% desirable_list as well.
desirable = sort(desirable_list, 'ascend');

% Our list and the sorted list.
A = [1.3, 2.2, 2.3, 4.2, 5.1, 3.2, 5.3, 3.3, 2.1, 1.1, 5.2, 3.1];
A_sorted = sort(A);

% Getting the integer parts (uniquely) of our list.
integer_parts = unique(fix(A));

% Getting the elements that satisfy our criteria in an ordered list in an
% array called S.
S = [];
for j = integer_parts
    m1 = (A_sorted(fix(A_sorted) == j));
    if m1 < 0
        m1 = sort(m1, 'descend');
    end


    if length(m1) == length(desirable) & abs(abs(m1) - desirable) < abs(j) + tolerance
        S = [S m1];
    end
end

% Getting the elements we are interested in, in the specific order they
% appear in our original list.

V = zeros(1,length(S));
l = 1;
for k = 1:length(A)
    if ismember(A(k), S)
        V(l)= A(k);
        l = l + 1;
    end
end
A
V

< Сильный > Вывод :

A =

    1.3000    2.2000    2.3000    4.2000    5.1000    3.2000    5.3000    3.3000    2.1000    1.1000    5.2000    3.1000


V =

    2.2000    2.3000    5.1000    3.2000    5.3000    3.3000    2.1000    5.2000    3.1000

>> 
0
thanasissdr 8 Янв 2017 в 01:32

С помощью Python вы можете использовать itertools.groupby, чтобы сгруппируйте числа с плавающей точкой по их значениям и убедитесь, что десятичные дроби являются надмножеством [1,2,3]:

from itertools import groupby
needed_decimals = set([1, 2, 3])

a = [1.3, 2.2, 2.3,4.2, 5.1, 3.2, 5.3, 3.3, 2.1,1.1, 5.2, 3.1]

pairs = [tuple(int(y) for y in str(x).split('.')) for x in sorted(a)]
#=> [(1, 1), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3), (4, 2), (5, 1), (5, 2), (5, 3)]
integers = [integer for integer, numbers in groupby(pairs, lambda x: x[0]) if set(x[1] for x in numbers) >= needed_decimals]
#=> [2,3,5]
0
Eric Duminil 7 Янв 2017 в 12:35

В Python вы можете сделать:

import operator

A = [1.3, 2.2, 2.3,4.2, 5.1, 3.2, 5.3, 3.3, 2.1,1.1, 5.2, 3.1]

s = set(int(str(i).split('.')[0]) for i in A)

res = []
for n in s:
    if all(x in A for x in map(operator.add, [n, n, n], [0.1, 0.2, 0.3])):
        res.append(n)

< Сильный > Вывод :

>>> res
[2, 3, 5]

< Сильный > Edit:

Если вы хотите получить числа с плавающей запятой, которые имеют .1, .2 и .3 за одним целым числом, попробуйте следующее:

for n in s:
    temp = map(operator.add, [n, n, n], [0.1, 0.2, 0.3])
    if all(x in A for x in temp):
        res.extend(temp)

< Сильный > Вывод :

>>> res
[2.1, 2.2, 2.3, 3.1, 3.2, 3.3, 5.1, 5.2, 5.3]
0
ettanany 7 Янв 2017 в 14:15

Решение MATLAB: (обновлено из-за обновления в вопросе)

A = [1.3, 2.2, 2.3,4.2, 5.1, 3.2, 5.3, 3.3, 2.1,1.1, 5.2, 3.1]
INC = [.1 .2 .3];
F = floor(A);
U = unique(F,'stable');
%find unique  values of F
B = bsxfun(@plus,U,INC.');
%with broadcasting sum each element with [.1 .2 .3]
%in MATLAB R2016b you can write B = U + INC.';
IDX = all(ismember(B,A));
%for each integer I if  I+[.1 .2 .3] exist in the array return index of it
OUT =B(:,IDX);
%extract output

Более компактная форма:

B = bsxfun(@plus,unique(floor(A),'stable'),INC.');
OUT = B(:,all(ismember(B,A)))

Что в MATLAB R2016b или Octave можно записать как:

B = unique(floor(A),'stable') + INC.';
OUT = B(:, all(ismember(B,A)))

Результат

OUT =

   2.1000   3.1000   5.1000
   2.2000   3.2000   5.2000
   2.3000   3.3000   5.3000
0
rahnema1 7 Янв 2017 в 14:44

Используя Python , вы можете сделать:

import numpy as np
A = [1.3, 2.2, 2.3, 4.2, 5.1, 3.2, 5.3, 3.3, 2.1, 1.1, 5.2, 3.1]
b = set([int(i) for i in A if np.all([j in A for j in (np.array([1, 2, 3]) + 10*int(np.floor(i)))/10.0])])

Где б

set([2, 3, 5])

(который может быть легко преобразован в список с помощью list).

< Сильный > Комментарии :

Я умножаю на 10 и делю на 10.0, чтобы избежать арифметических проблем с плавающей запятой. В вопросе неясно, хотите ли вы, чтобы сравнение было числовым или строковым.

0
oliversm 7 Янв 2017 в 12:15

установлено ([x для x в карте (int, l), если все ([float (str (x) + '.' + str (e)) в l для e в [1,2,3]]) ] )

Делает трюк в одну строку

0
louis35 7 Янв 2017 в 17:16